From 0e010a69926d400262626dd13803890e00e2598c Mon Sep 17 00:00:00 2001 From: Alexis Bourget Date: Wed, 12 Aug 2020 22:58:18 +0200 Subject: [PATCH 01/12] Move to intra doc links for ascii.rs and panic.rs, updating the docs a little --- library/std/src/ascii.rs | 23 ++++++++++------------- library/std/src/panic.rs | 17 ----------------- 2 files changed, 10 insertions(+), 30 deletions(-) diff --git a/library/std/src/ascii.rs b/library/std/src/ascii.rs index 5cd2a25b11768..c9106136d3441 100644 --- a/library/std/src/ascii.rs +++ b/library/std/src/ascii.rs @@ -10,9 +10,6 @@ //! //! The [`escape_default`] function provides an iterator over the bytes of an //! escaped version of the character given. -//! -//! [`AsciiExt`]: trait.AsciiExt.html -//! [`escape_default`]: fn.escape_default.html #![stable(feature = "rust1", since = "1.0.0")] @@ -52,7 +49,7 @@ pub trait AsciiExt { /// /// # Note /// - /// This method will be deprecated in favor of the identically-named + /// This method is deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[stable(feature = "rust1", since = "1.0.0")] fn is_ascii(&self) -> bool; @@ -69,10 +66,10 @@ pub trait AsciiExt { /// /// # Note /// - /// This method will be deprecated in favor of the identically-named + /// This method is deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. /// - /// [`make_ascii_uppercase`]: #tymethod.make_ascii_uppercase + /// [`make_ascii_uppercase`]: AsciiExt::make_ascii_uppercase /// [`str::to_uppercase`]: ../primitive.str.html#method.to_uppercase #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] @@ -90,10 +87,10 @@ pub trait AsciiExt { /// /// # Note /// - /// This method will be deprecated in favor of the identically-named + /// This method is deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. /// - /// [`make_ascii_lowercase`]: #tymethod.make_ascii_lowercase + /// [`make_ascii_lowercase`]: AsciiExt::make_ascii_lowercase /// [`str::to_lowercase`]: ../primitive.str.html#method.to_lowercase #[stable(feature = "rust1", since = "1.0.0")] #[allow(deprecated)] @@ -106,7 +103,7 @@ pub trait AsciiExt { /// /// # Note /// - /// This method will be deprecated in favor of the identically-named + /// This method is deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. #[stable(feature = "rust1", since = "1.0.0")] fn eq_ignore_ascii_case(&self, other: &Self) -> bool; @@ -121,10 +118,10 @@ pub trait AsciiExt { /// /// # Note /// - /// This method will be deprecated in favor of the identically-named + /// This method is deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. /// - /// [`to_ascii_uppercase`]: #tymethod.to_ascii_uppercase + /// [`to_ascii_uppercase`]: AsciiExt::to_ascii_uppercase #[stable(feature = "ascii", since = "1.9.0")] fn make_ascii_uppercase(&mut self); @@ -138,10 +135,10 @@ pub trait AsciiExt { /// /// # Note /// - /// This method will be deprecated in favor of the identically-named + /// This method is deprecated in favor of the identically-named /// inherent methods on `u8`, `char`, `[u8]` and `str`. /// - /// [`to_ascii_lowercase`]: #tymethod.to_ascii_lowercase + /// [`to_ascii_lowercase`]: AsciiExt::to_ascii_lowercase #[stable(feature = "ascii", since = "1.9.0")] fn make_ascii_lowercase(&mut self); } diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 6ad5519d34aa9..8fcb24033b1a7 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -30,10 +30,6 @@ pub use core::panic::{Location, PanicInfo}; /// purpose of this trait is to encode what types are safe to cross a [`catch_unwind`] /// boundary with no fear of unwind safety. /// -/// [`Send`]: ../marker/trait.Send.html -/// [`Sync`]: ../marker/trait.Sync.html -/// [`catch_unwind`]: ./fn.catch_unwind.html -/// /// ## What is unwind safety? /// /// In Rust a function can "return" early if it either panics or calls a @@ -99,8 +95,6 @@ pub use core::panic::{Location, PanicInfo}; /// above, the lack of `unsafe` means it is mostly an advisory. The /// [`AssertUnwindSafe`] wrapper struct can be used to force this trait to be /// implemented for any closed over variables passed to `catch_unwind`. -/// -/// [`AssertUnwindSafe`]: ./struct.AssertUnwindSafe.html #[stable(feature = "catch_unwind", since = "1.9.0")] #[rustc_on_unimplemented( message = "the type `{Self}` may not be safely transferred across an unwind boundary", @@ -116,9 +110,6 @@ pub auto trait UnwindSafe {} /// /// This is a "helper marker trait" used to provide impl blocks for the /// [`UnwindSafe`] trait, for more information see that documentation. -/// -/// [`UnsafeCell`]: ../cell/struct.UnsafeCell.html -/// [`UnwindSafe`]: ./trait.UnwindSafe.html #[stable(feature = "catch_unwind", since = "1.9.0")] #[rustc_on_unimplemented( message = "the type `{Self}` may contain interior mutability and a reference may not be safely \ @@ -138,7 +129,6 @@ pub auto trait RefUnwindSafe {} /// account. This wrapper struct is useful for a quick and lightweight /// annotation that a variable is indeed unwind safe. /// -/// [`catch_unwind`]: ./fn.catch_unwind.html /// # Examples /// /// One way to use `AssertUnwindSafe` is to assert that the entire closure @@ -352,8 +342,6 @@ impl Future for AssertUnwindSafe { /// can fail on a regular basis. Additionally, this function is not guaranteed /// to catch all panics, see the "Notes" section below. /// -/// [`Result`]: ../result/enum.Result.html -/// /// The closure provided is required to adhere to the [`UnwindSafe`] trait to ensure /// that all captured variables are safe to cross this boundary. The purpose of /// this bound is to encode the concept of [exception safety][rfc] in the type @@ -362,9 +350,6 @@ impl Future for AssertUnwindSafe { /// becomes a problem the [`AssertUnwindSafe`] wrapper struct can be used to quickly /// assert that the usage here is indeed unwind safe. /// -/// [`AssertUnwindSafe`]: ./struct.AssertUnwindSafe.html -/// [`UnwindSafe`]: ./trait.UnwindSafe.html -/// /// [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1236-stabilize-catch-panic.md /// /// # Notes @@ -399,8 +384,6 @@ pub fn catch_unwind R + UnwindSafe, R>(f: F) -> Result { /// This is designed to be used in conjunction with [`catch_unwind`] to, for /// example, carry a panic across a layer of C code. /// -/// [`catch_unwind`]: ./fn.catch_unwind.html -/// /// # Notes /// /// Note that panics in Rust are not always implemented via unwinding, but they From ac73474c7db65e49d3fd17906b7d34d984a88172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 16 Aug 2020 18:33:30 -0700 Subject: [PATCH 02/12] Add explanation for `&mut self` method call when expecting `-> Self` When a user tries to use a method as if it returned a new value of the same type as its receiver, we will emit a type error. Try to detect this and provide extra explanation that the method modifies the receiver in-place. This has confused people in the wild, like in https://users.rust-lang.org/t/newbie-why-the-commented-line-stops-the-snippet-from-compiling/47322 --- src/librustc_typeck/check/demand.rs | 1 + src/librustc_typeck/check/mod.rs | 45 +++++++++++++++++++ .../chain-method-call-mutation-in-place.rs | 4 ++ ...chain-method-call-mutation-in-place.stderr | 20 +++++++++ 4 files changed, 70 insertions(+) create mode 100644 src/test/ui/suggestions/chain-method-call-mutation-in-place.rs create mode 100644 src/test/ui/suggestions/chain-method-call-mutation-in-place.stderr diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 258c5b77df25b..3c367774d68ab 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -35,6 +35,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.suggest_boxing_when_appropriate(err, expr, expected, expr_ty); self.suggest_missing_await(err, expr, expected, expr_ty); self.note_need_for_fn_pointer(err, expected, expr_ty); + self.note_internal_mutation_in_method(err, expr, expected, expr_ty); } // Requires that the two types unify, and prints an error message if diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index a40b6860f7765..6dd7f0661b893 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5176,6 +5176,51 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + fn note_internal_mutation_in_method( + &self, + err: &mut DiagnosticBuilder<'_>, + expr: &hir::Expr<'_>, + expected: Ty<'tcx>, + found: Ty<'tcx>, + ) { + if found != self.tcx.types.unit { + return; + } + if let ExprKind::MethodCall(path_segment, _, [rcvr, ..], _) = expr.kind { + if self + .typeck_results + .borrow() + .expr_ty_adjusted_opt(rcvr) + .map_or(true, |ty| expected.peel_refs() != ty.peel_refs()) + { + return; + } + let mut sp = MultiSpan::from_span(path_segment.ident.span); + sp.push_span_label( + path_segment.ident.span, + format!( + "this call modifies {} in-place", + match rcvr.kind { + ExprKind::Path(QPath::Resolved( + None, + hir::Path { segments: [segment], .. }, + )) => format!("`{}`", segment.ident), + _ => "its receiver".to_string(), + } + ), + ); + sp.push_span_label( + rcvr.span, + "you probably want to use this value after calling the method...".to_string(), + ); + err.span_note( + sp, + &format!("method `{}` modifies its receiver in-place", path_segment.ident), + ); + err.note(&format!("...instead of the `()` output of method `{}`", path_segment.ident)); + } + } + /// When encountering an `impl Future` where `BoxFuture` is expected, suggest `Box::pin`. fn suggest_calling_boxed_future_when_appropriate( &self, diff --git a/src/test/ui/suggestions/chain-method-call-mutation-in-place.rs b/src/test/ui/suggestions/chain-method-call-mutation-in-place.rs new file mode 100644 index 0000000000000..cb92ab87a8ff7 --- /dev/null +++ b/src/test/ui/suggestions/chain-method-call-mutation-in-place.rs @@ -0,0 +1,4 @@ +fn main() {} +fn foo(mut s: String) -> String { + s.push_str("asdf") //~ ERROR mismatched types +} diff --git a/src/test/ui/suggestions/chain-method-call-mutation-in-place.stderr b/src/test/ui/suggestions/chain-method-call-mutation-in-place.stderr new file mode 100644 index 0000000000000..63e3bb78954cf --- /dev/null +++ b/src/test/ui/suggestions/chain-method-call-mutation-in-place.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/chain-method-call-mutation-in-place.rs:3:5 + | +LL | fn foo(mut s: String) -> String { + | ------ expected `std::string::String` because of return type +LL | s.push_str("asdf") + | ^^^^^^^^^^^^^^^^^^ expected struct `std::string::String`, found `()` + | +note: method `push_str` modifies its receiver in-place + --> $DIR/chain-method-call-mutation-in-place.rs:3:7 + | +LL | s.push_str("asdf") + | - ^^^^^^^^ this call modifies `s` in-place + | | + | you probably want to use this value after calling the method... + = note: ...instead of the `()` output of method `push_str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. From be1fc40b1d473e8c1b22662d58e631c4f586d881 Mon Sep 17 00:00:00 2001 From: 5M1Sec <332047956+TsukimiSerenade@users.noreply.github.com> Date: Sat, 15 Aug 2020 23:39:09 -0400 Subject: [PATCH 03/12] Allowing raw ptr dereference in const fn Change `UnsafetyViolationKind::General` to `UnsafetyViolationKind::GeneralAndConstFn` in check_unsafety.rs Remove unsafe in min_const_fn_unsafe_bad.rs Bless min_const_fn Add the test case from issue 75340 Co-authored-by: lzutao --- src/librustc_mir/transform/check_unsafety.rs | 2 +- .../allow_raw_ptr_dereference_const_fn.rs | 11 +++++++++++ .../consts/min_const_fn/min_const_fn_unsafe_bad.rs | 2 +- .../min_const_fn/min_const_fn_unsafe_bad.stderr | 14 +++----------- 4 files changed, 16 insertions(+), 13 deletions(-) create mode 100644 src/test/ui/consts/min_const_fn/allow_raw_ptr_dereference_const_fn.rs diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index d2a5616b8ed34..6aabc1941a65e 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -228,7 +228,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { let base_ty = Place::ty_from(place.local, proj_base, self.body, self.tcx).ty; match base_ty.kind { ty::RawPtr(..) => self.require_unsafe( - UnsafetyViolationKind::General, + UnsafetyViolationKind::GeneralAndConstFn, UnsafetyViolationDetails::DerefOfRawPointer, ), ty::Adt(adt, _) => { diff --git a/src/test/ui/consts/min_const_fn/allow_raw_ptr_dereference_const_fn.rs b/src/test/ui/consts/min_const_fn/allow_raw_ptr_dereference_const_fn.rs new file mode 100644 index 0000000000000..25dc457d14455 --- /dev/null +++ b/src/test/ui/consts/min_const_fn/allow_raw_ptr_dereference_const_fn.rs @@ -0,0 +1,11 @@ +// check-pass +#![feature(const_raw_ptr_deref)] +#![feature(raw_ref_macros)] + +use std::ptr; + +const fn test_fn(x: *const i32) { + let x2 = unsafe { ptr::raw_const!(*x) }; +} + +fn main() {} diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs index 0b1ab1c34ff2f..6462d736ad194 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.rs @@ -1,4 +1,4 @@ -const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } //~ is unsafe +const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } //~^ dereferencing raw pointers in constant functions const unsafe fn bad_const_unsafe_deref_raw(x: *mut usize) -> usize { *x } diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr index 97b0a778d2c72..427ecff5c6d1a 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_unsafe_bad.stderr @@ -34,15 +34,7 @@ LL | Foo { x: () }.y = note: see issue #57563 for more information = help: add `#![feature(const_fn)]` to the crate attributes to enable -error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block - --> $DIR/min_const_fn_unsafe_bad.rs:1:77 - | -LL | const fn bad_const_fn_deref_raw(x: *mut usize) -> &'static usize { unsafe { &*x } } - | ^^^ dereference of raw pointer - | - = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior - -error: aborting due to 5 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0133, E0658, E0723. -For more information about an error, try `rustc --explain E0133`. +Some errors have detailed explanations: E0658, E0723. +For more information about an error, try `rustc --explain E0658`. From bdbb995df331e6bdd49b182d4f24577e18df7abd Mon Sep 17 00:00:00 2001 From: Sasha Date: Mon, 17 Aug 2020 12:44:18 +0200 Subject: [PATCH 04/12] Mark x86_64-linux-kernel as * --- src/doc/rustc/src/platform-support.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 61261e82147ce..21874853839bd 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -204,7 +204,7 @@ target | std | host | notes `thumbv4t-none-eabi` | * | | ARMv4T T32 `x86_64-apple-ios-macabi` | ✓[^apple] | | Apple Catalyst `x86_64-apple-tvos` | *[^apple] | | x86 64-bit tvOS -`x86_64-linux-kernel` | ? | | Linux kernel modules +`x86_64-linux-kernel` | * | | Linux kernel modules `x86_64-pc-solaris` | ? | | `x86_64-pc-windows-msvc` | ✓ | | 64-bit Windows XP support `x86_64-unknown-cloudabi` | ✓ | | 64-bit CloudABI From edb39c0d208ef7850116bd3c931df091730c0e7f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 11 Aug 2020 09:42:25 +0200 Subject: [PATCH 05/12] attempt to improve span_label docs --- src/librustc_errors/diagnostic.rs | 15 ++++++++------- src/librustc_errors/diagnostic_builder.rs | 14 +++++++++----- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs index acaa26c6ad2fc..d0ad5a06e982e 100644 --- a/src/librustc_errors/diagnostic.rs +++ b/src/librustc_errors/diagnostic.rs @@ -127,14 +127,15 @@ impl Diagnostic { } /// Adds a span/label to be included in the resulting snippet. - /// This label will be shown together with the original span/label used when creating the - /// diagnostic, *not* a span added by one of the `span_*` methods. /// - /// This is pushed onto the `MultiSpan` that was created when the - /// diagnostic was first built. If you don't call this function at - /// all, and you just supplied a `Span` to create the diagnostic, - /// then the snippet will just include that `Span`, which is - /// called the primary span. + /// This is pushed onto the [`MultiSpan`] that was created when the diagnostic + /// was first built. That means it will be shown together with the original + /// span/label, *not* a span added by one of the `span_{note,warn,help,suggestions}` methods. + /// + /// This span is *not* considered a ["primary span"][`MultiSpan`]; only + /// the `Span` supplied when creating the diagnostic is primary. + /// + /// [`MultiSpan`]: ../rustc_span/struct.MultiSpan.html pub fn span_label>(&mut self, span: Span, label: T) -> &mut Self { self.span.push_span_label(span, label.into()); self diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs index 22bf8fe34aa15..b8a6dd73952dc 100644 --- a/src/librustc_errors/diagnostic_builder.rs +++ b/src/librustc_errors/diagnostic_builder.rs @@ -184,11 +184,15 @@ impl<'a> DiagnosticBuilder<'a> { } /// Adds a span/label to be included in the resulting snippet. - /// This is pushed onto the `MultiSpan` that was created when the - /// diagnostic was first built. If you don't call this function at - /// all, and you just supplied a `Span` to create the diagnostic, - /// then the snippet will just include that `Span`, which is - /// called the primary span. + /// + /// This is pushed onto the [`MultiSpan`] that was created when the diagnostic + /// was first built. That means it will be shown together with the original + /// span/label, *not* a span added by one of the `span_{note,warn,help,suggestions}` methods. + /// + /// This span is *not* considered a ["primary span"][`MultiSpan`]; only + /// the `Span` supplied when creating the diagnostic is primary. + /// + /// [`MultiSpan`]: ../rustc_span/struct.MultiSpan.html pub fn span_label(&mut self, span: Span, label: impl Into) -> &mut Self { self.0.diagnostic.span_label(span, label); self From 93e074bc8a0766afbe3594f8663d702638ec0c35 Mon Sep 17 00:00:00 2001 From: Tim Diekmann Date: Mon, 17 Aug 2020 14:22:59 +0200 Subject: [PATCH 06/12] Add `as_uninit`-like methods to pointer types and unify documentation of `as_ref` methods Fix example in `NonNull::as_uninit_slice` Rename feature gate to "ptr_as_uninit" Make methods more consistent with already stable methods Make `pointer::as_uninit_slice` return an `Option` Fix placement for `// SAFETY` section Add `as_uninit_ref` and `as_uninit_mut` to pointers Fix doctest Update tracking issue Fix doc links Apply suggestions from review Make wording about counterparts consistent Fix doc links Improve documentation Fix doc-tests Fix doc links ... again Apply suggestions from review Apply suggestions from Review Apply suggestion from review to all affected files Add missing words in safety sections in `as_uninit_slice_mut` Fix safety-comment in `NonNull::as_uninit_slice_mut` --- library/core/src/lib.rs | 1 + library/core/src/ptr/const_ptr.rs | 134 +++++++++++++-- library/core/src/ptr/mut_ptr.rs | 273 ++++++++++++++++++++++++++---- library/core/src/ptr/non_null.rs | 241 ++++++++++++++++++++++---- 4 files changed, 568 insertions(+), 81 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index fcf5454308b47..26568cdcf9bee 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -114,6 +114,7 @@ #![feature(optin_builtin_traits)] #![feature(or_patterns)] #![feature(prelude_import)] +#![feature(ptr_as_uninit)] #![feature(repr_simd, platform_intrinsics)] #![feature(rustc_attrs)] #![feature(simd_ffi)] diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index a16970e9fd180..493cfe4992b6d 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -2,7 +2,7 @@ use super::*; use crate::cmp::Ordering::{self, Equal, Greater, Less}; use crate::intrinsics; use crate::mem; -use crate::slice::SliceIndex; +use crate::slice::{self, SliceIndex}; #[lang = "const_ptr"] impl *const T { @@ -38,32 +38,33 @@ impl *const T { self as _ } - /// Returns `None` if the pointer is null, or else returns a reference to - /// the value wrapped in `Some`. + /// Returns `None` if the pointer is null, or else returns a shared reference to + /// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_ref`] + /// must be used instead. /// - /// # Safety + /// [`as_uninit_ref`]: #method.as_uninit_ref /// - /// While this method and its mutable counterpart are useful for - /// null-safety, it is important to note that this is still an unsafe - /// operation because the returned value could be pointing to invalid - /// memory. + /// # Safety /// /// When calling this method, you have to ensure that *either* the pointer is NULL *or* /// all of the following is true: - /// - it is properly aligned - /// - it must point to an initialized instance of T; in particular, the pointer must be - /// "dereferenceable" in the sense defined [here]. + /// + /// * The pointer must be properly aligned. + /// + /// * It must be "dereferencable" in the sense defined in [the module documentation]. + /// + /// * The pointer must point to an initialized instance of `T`. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, for the duration of this lifetime, the memory the pointer points to must + /// not get mutated (except inside `UnsafeCell`). /// /// This applies even if the result of this method is unused! /// (The part about being initialized is not yet fully decided, but until /// it is, the only safe approach is to ensure that they are indeed initialized.) /// - /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does - /// not necessarily reflect the actual lifetime of the data. *You* must enforce - /// Rust's aliasing rules. In particular, for the duration of this lifetime, - /// the memory the pointer points to must not get mutated (except inside `UnsafeCell`). - /// - /// [here]: crate::ptr#safety + /// [the module documentation]: crate::ptr#safety /// /// # Examples /// @@ -101,6 +102,56 @@ impl *const T { if self.is_null() { None } else { unsafe { Some(&*self) } } } + /// Returns `None` if the pointer is null, or else returns a shared reference to + /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require + /// that the value has to be initialized. + /// + /// [`as_ref`]: #method.as_ref + /// + /// # Safety + /// + /// When calling this method, you have to ensure that *either* the pointer is NULL *or* + /// all of the following is true: + /// + /// * The pointer must be properly aligned. + /// + /// * It must be "dereferencable" in the sense defined in [the module documentation]. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, for the duration of this lifetime, the memory the pointer points to must + /// not get mutated (except inside `UnsafeCell`). + /// + /// This applies even if the result of this method is unused! + /// + /// [the module documentation]: crate::ptr#safety + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(ptr_as_uninit)] + /// + /// let ptr: *const u8 = &10u8 as *const u8; + /// + /// unsafe { + /// if let Some(val_back) = ptr.as_uninit_ref() { + /// println!("We got back the value: {}!", val_back.assume_init()); + /// } + /// } + /// ``` + #[inline] + #[unstable(feature = "ptr_as_uninit", issue = "75402")] + pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit> + where + T: Sized, + { + // SAFETY: the caller must guarantee that `self` meets all the + // requirements for a reference. + if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit) }) } + } + /// Calculates the offset from a pointer. /// /// `count` is in units of T; e.g., a `count` of 3 represents a pointer @@ -906,6 +957,55 @@ impl *const [T] { // SAFETY: the caller ensures that `self` is dereferencable and `index` in-bounds. unsafe { index.get_unchecked(self) } } + + /// Returns `None` if the pointer is null, or else returns a shared slice to + /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require + /// that the value has to be initialized. + /// + /// [`as_ref`]: #method.as_ref + /// + /// # Safety + /// + /// When calling this method, you have to ensure that *either* the pointer is NULL *or* + /// all of the following is true: + /// + /// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::()` many bytes, + /// and it must be properly aligned. This means in particular: + /// + /// * The entire memory range of this slice must be contained within a single allocated object! + /// Slices can never span across multiple allocated objects. + /// + /// * The pointer must be aligned even for zero-length slices. One + /// reason for this is that enum layout optimizations may rely on references + /// (including slices of any length) being aligned and non-null to distinguish + /// them from other data. You can obtain a pointer that is usable as `data` + /// for zero-length slices using [`NonNull::dangling()`]. + /// + /// * The total size `ptr.len() * mem::size_of::()` of the slice must be no larger than `isize::MAX`. + /// See the safety documentation of [`pointer::offset`]. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, for the duration of this lifetime, the memory the pointer points to must + /// not get mutated (except inside `UnsafeCell`). + /// + /// This applies even if the result of this method is unused! + /// + /// See also [`slice::from_raw_parts`][]. + /// + /// [valid]: crate::ptr#safety + /// [`NonNull::dangling()`]: NonNull::dangling + /// [`pointer::offset`]: ../std/primitive.pointer.html#method.offset + #[inline] + #[unstable(feature = "ptr_as_uninit", issue = "75402")] + pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit]> { + if self.is_null() { + None + } else { + // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`. + Some(unsafe { slice::from_raw_parts(self as *const MaybeUninit, self.len()) }) + } + } } // Equality for pointers diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index b47f90c599629..eeb425de262be 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -1,7 +1,7 @@ use super::*; use crate::cmp::Ordering::{self, Equal, Greater, Less}; use crate::intrinsics; -use crate::slice::SliceIndex; +use crate::slice::{self, SliceIndex}; #[lang = "mut_ptr"] impl *mut T { @@ -37,32 +37,36 @@ impl *mut T { self as _ } - /// Returns `None` if the pointer is null, or else returns a reference to - /// the value wrapped in `Some`. + /// Returns `None` if the pointer is null, or else returns a shared reference to + /// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_ref`] + /// must be used instead. /// - /// # Safety + /// For the mutable counterpart see [`as_mut`]. + /// + /// [`as_uninit_ref`]: #method.as_uninit_ref-1 + /// [`as_mut`]: #method.as_mut /// - /// While this method and its mutable counterpart are useful for - /// null-safety, it is important to note that this is still an unsafe - /// operation because the returned value could be pointing to invalid - /// memory. + /// # Safety /// /// When calling this method, you have to ensure that *either* the pointer is NULL *or* /// all of the following is true: - /// - it is properly aligned - /// - it must point to an initialized instance of T; in particular, the pointer must be - /// "dereferencable" in the sense defined [here]. + /// + /// * The pointer must be properly aligned. + /// + /// * It must be "dereferencable" in the sense defined in [the module documentation]. + /// + /// * The pointer must point to an initialized instance of `T`. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, for the duration of this lifetime, the memory the pointer points to must + /// not get mutated (except inside `UnsafeCell`). /// /// This applies even if the result of this method is unused! /// (The part about being initialized is not yet fully decided, but until /// it is, the only safe approach is to ensure that they are indeed initialized.) /// - /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does - /// not necessarily reflect the actual lifetime of the data. *You* must enforce - /// Rust's aliasing rules. In particular, for the duration of this lifetime, - /// the memory the pointer points to must not get mutated (except inside `UnsafeCell`). - /// - /// [here]: crate::ptr#safety + /// [the module documentation]: crate::ptr#safety /// /// # Examples /// @@ -100,6 +104,59 @@ impl *mut T { if self.is_null() { None } else { unsafe { Some(&*self) } } } + /// Returns `None` if the pointer is null, or else returns a shared reference to + /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require + /// that the value has to be initialized. + /// + /// For the mutable counterpart see [`as_uninit_mut`]. + /// + /// [`as_ref`]: #method.as_ref-1 + /// [`as_uninit_mut`]: #method.as_uninit_mut + /// + /// # Safety + /// + /// When calling this method, you have to ensure that *either* the pointer is NULL *or* + /// all of the following is true: + /// + /// * The pointer must be properly aligned. + /// + /// * It must be "dereferencable" in the sense defined in [the module documentation]. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, for the duration of this lifetime, the memory the pointer points to must + /// not get mutated (except inside `UnsafeCell`). + /// + /// This applies even if the result of this method is unused! + /// + /// [the module documentation]: crate::ptr#safety + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(ptr_as_uninit)] + /// + /// let ptr: *mut u8 = &mut 10u8 as *mut u8; + /// + /// unsafe { + /// if let Some(val_back) = ptr.as_uninit_ref() { + /// println!("We got back the value: {}!", val_back.assume_init()); + /// } + /// } + /// ``` + #[inline] + #[unstable(feature = "ptr_as_uninit", issue = "75402")] + pub unsafe fn as_uninit_ref<'a>(self) -> Option<&'a MaybeUninit> + where + T: Sized, + { + // SAFETY: the caller must guarantee that `self` meets all the + // requirements for a reference. + if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit) }) } + } + /// Calculates the offset from a pointer. /// /// `count` is in units of T; e.g., a `count` of 3 represents a pointer @@ -225,33 +282,36 @@ impl *mut T { unsafe { intrinsics::arith_offset(self, count) as *mut T } } - /// Returns `None` if the pointer is null, or else returns a mutable - /// reference to the value wrapped in `Some`. + /// Returns `None` if the pointer is null, or else returns a unique reference to + /// the value wrapped in `Some`. If the value may be uninitialized, [`as_uninit_mut`] + /// must be used instead. /// - /// # Safety + /// For the shared counterpart see [`as_ref`]. /// - /// As with [`as_ref`], this is unsafe because it cannot verify the validity - /// of the returned pointer, nor can it ensure that the lifetime `'a` - /// returned is indeed a valid lifetime for the contained data. + /// [`as_uninit_mut`]: #method.as_uninit_mut + /// [`as_ref`]: #method.as_ref-1 + /// + /// # Safety /// /// When calling this method, you have to ensure that *either* the pointer is NULL *or* /// all of the following is true: - /// - it is properly aligned - /// - it must point to an initialized instance of T; in particular, the pointer must be - /// "dereferenceable" in the sense defined [here]. + /// + /// * The pointer must be properly aligned. + /// + /// * It must be "dereferencable" in the sense defined in [the module documentation]. + /// + /// * The pointer must point to an initialized instance of `T`. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, for the duration of this lifetime, the memory the pointer points to must + /// not get accessed (read or written) through any other pointer. /// /// This applies even if the result of this method is unused! /// (The part about being initialized is not yet fully decided, but until - /// it is the only safe approach is to ensure that they are indeed initialized.) - /// - /// Additionally, the lifetime `'a` returned is arbitrarily chosen and does - /// not necessarily reflect the actual lifetime of the data. *You* must enforce - /// Rust's aliasing rules. In particular, for the duration of this lifetime, - /// the memory this pointer points to must not get accessed (read or written) - /// through any other pointer. + /// it is, the only safe approach is to ensure that they are indeed initialized.) /// - /// [here]: crate::ptr#safety - /// [`as_ref`]: #method.as_ref + /// [the module documentation]: crate::ptr#safety /// /// # Examples /// @@ -262,6 +322,7 @@ impl *mut T { /// let ptr: *mut u32 = s.as_mut_ptr(); /// let first_value = unsafe { ptr.as_mut().unwrap() }; /// *first_value = 4; + /// # assert_eq!(s, [4, 2, 3]); /// println!("{:?}", s); // It'll print: "[4, 2, 3]". /// ``` /// @@ -276,6 +337,7 @@ impl *mut T { /// let ptr: *mut u32 = s.as_mut_ptr(); /// let first_value = unsafe { &mut *ptr }; /// *first_value = 4; + /// # assert_eq!(s, [4, 2, 3]); /// println!("{:?}", s); // It'll print: "[4, 2, 3]". /// ``` #[stable(feature = "ptr_as_ref", since = "1.9.0")] @@ -286,6 +348,43 @@ impl *mut T { if self.is_null() { None } else { unsafe { Some(&mut *self) } } } + /// Returns `None` if the pointer is null, or else returns a unique reference to + /// the value wrapped in `Some`. In contrast to [`as_mut`], this does not require + /// that the value has to be initialized. + /// + /// For the shared counterpart see [`as_uninit_ref`]. + /// + /// [`as_mut`]: #method.as_mut + /// [`as_uninit_ref`]: #method.as_uninit_ref-1 + /// + /// # Safety + /// + /// When calling this method, you have to ensure that *either* the pointer is NULL *or* + /// all of the following is true: + /// + /// * The pointer must be properly aligned. + /// + /// * It must be "dereferencable" in the sense defined in [the module documentation]. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, for the duration of this lifetime, the memory the pointer points to must + /// not get accessed (read or written) through any other pointer. + /// + /// This applies even if the result of this method is unused! + /// + /// [the module documentation]: crate::ptr#safety + #[inline] + #[unstable(feature = "ptr_as_uninit", issue = "75402")] + pub unsafe fn as_uninit_mut<'a>(self) -> Option<&'a mut MaybeUninit> + where + T: Sized, + { + // SAFETY: the caller must guarantee that `self` meets all the + // requirements for a reference. + if self.is_null() { None } else { Some(unsafe { &mut *(self as *mut MaybeUninit) }) } + } + /// Returns whether two pointers are guaranteed to be equal. /// /// At runtime this function behaves like `self == other`. @@ -1112,6 +1211,110 @@ impl *mut [T] { // SAFETY: the caller ensures that `self` is dereferencable and `index` in-bounds. unsafe { index.get_unchecked_mut(self) } } + + /// Returns `None` if the pointer is null, or else returns a shared slice to + /// the value wrapped in `Some`. In contrast to [`as_ref`], this does not require + /// that the value has to be initialized. + /// + /// For the mutable counterpart see [`as_uninit_slice_mut`]. + /// + /// [`as_ref`]: #method.as_ref-1 + /// [`as_uninit_slice_mut`]: #method.as_uninit_slice_mut + /// + /// # Safety + /// + /// When calling this method, you have to ensure that *either* the pointer is NULL *or* + /// all of the following is true: + /// + /// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::()` many bytes, + /// and it must be properly aligned. This means in particular: + /// + /// * The entire memory range of this slice must be contained within a single allocated object! + /// Slices can never span across multiple allocated objects. + /// + /// * The pointer must be aligned even for zero-length slices. One + /// reason for this is that enum layout optimizations may rely on references + /// (including slices of any length) being aligned and non-null to distinguish + /// them from other data. You can obtain a pointer that is usable as `data` + /// for zero-length slices using [`NonNull::dangling()`]. + /// + /// * The total size `ptr.len() * mem::size_of::()` of the slice must be no larger than `isize::MAX`. + /// See the safety documentation of [`pointer::offset`]. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, for the duration of this lifetime, the memory the pointer points to must + /// not get mutated (except inside `UnsafeCell`). + /// + /// This applies even if the result of this method is unused! + /// + /// See also [`slice::from_raw_parts`][]. + /// + /// [valid]: crate::ptr#safety + /// [`NonNull::dangling()`]: NonNull::dangling + /// [`pointer::offset`]: ../std/primitive.pointer.html#method.offset + #[inline] + #[unstable(feature = "ptr_as_uninit", issue = "75402")] + pub unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit]> { + if self.is_null() { + None + } else { + // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`. + Some(unsafe { slice::from_raw_parts(self as *const MaybeUninit, self.len()) }) + } + } + + /// Returns `None` if the pointer is null, or else returns a unique slice to + /// the value wrapped in `Some`. In contrast to [`as_mut`], this does not require + /// that the value has to be initialized. + /// + /// For the shared counterpart see [`as_uninit_slice`]. + /// + /// [`as_mut`]: #method.as_mut + /// [`as_uninit_slice`]: #method.as_uninit_slice-1 + /// + /// # Safety + /// + /// When calling this method, you have to ensure that *either* the pointer is NULL *or* + /// all of the following is true: + /// + /// * The pointer must be [valid] for reads and writes for `ptr.len() * mem::size_of::()` + /// many bytes, and it must be properly aligned. This means in particular: + /// + /// * The entire memory range of this slice must be contained within a single allocated object! + /// Slices can never span across multiple allocated objects. + /// + /// * The pointer must be aligned even for zero-length slices. One + /// reason for this is that enum layout optimizations may rely on references + /// (including slices of any length) being aligned and non-null to distinguish + /// them from other data. You can obtain a pointer that is usable as `data` + /// for zero-length slices using [`NonNull::dangling()`]. + /// + /// * The total size `ptr.len() * mem::size_of::()` of the slice must be no larger than `isize::MAX`. + /// See the safety documentation of [`pointer::offset`]. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, for the duration of this lifetime, the memory the pointer points to must + /// not get accessed (read or written) through any other pointer. + /// + /// This applies even if the result of this method is unused! + /// + /// See also [`slice::from_raw_parts_mut`][]. + /// + /// [valid]: crate::ptr#safety + /// [`NonNull::dangling()`]: NonNull::dangling + /// [`pointer::offset`]: ../std/primitive.pointer.html#method.offset + #[inline] + #[unstable(feature = "ptr_as_uninit", issue = "75402")] + pub unsafe fn as_uninit_slice_mut<'a>(self) -> Option<&'a mut [MaybeUninit]> { + if self.is_null() { + None + } else { + // SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`. + Some(unsafe { slice::from_raw_parts_mut(self as *mut MaybeUninit, self.len()) }) + } + } } // Equality for pointers diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index d876ab23653f3..294a3173d0cbf 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -3,10 +3,10 @@ use crate::convert::From; use crate::fmt; use crate::hash; use crate::marker::Unsize; -use crate::mem; +use crate::mem::{self, MaybeUninit}; use crate::ops::{CoerceUnsized, DispatchFromDyn}; use crate::ptr::Unique; -use crate::slice::SliceIndex; +use crate::slice::{self, SliceIndex}; /// `*mut T` but non-zero and covariant. /// @@ -76,6 +76,70 @@ impl NonNull { NonNull::new_unchecked(ptr) } } + + /// Returns a shared references to the value. In contrast to [`as_ref`], this does not require + /// that the value has to be initialized. + /// + /// For the mutable counterpart see [`as_uninit_mut`]. + /// + /// [`as_ref`]: #method.as_ref + /// [`as_uninit_mut`]: #method.as_uninit_mut + /// + /// # Safety + /// + /// When calling this method, you have to ensure that all of the following is true: + /// + /// * The pointer must be properly aligned. + /// + /// * It must be "dereferencable" in the sense defined in [the module documentation]. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, for the duration of this lifetime, the memory the pointer points to must + /// not get mutated (except inside `UnsafeCell`). + /// + /// This applies even if the result of this method is unused! + /// + /// [the module documentation]: crate::ptr#safety + #[inline] + #[unstable(feature = "ptr_as_uninit", issue = "75402")] + pub unsafe fn as_uninit_ref(&self) -> &MaybeUninit { + // SAFETY: the caller must guarantee that `self` meets all the + // requirements for a reference. + unsafe { &*self.cast().as_ptr() } + } + + /// Returns a unique references to the value. In contrast to [`as_mut`], this does not require + /// that the value has to be initialized. + /// + /// For the shared counterpart see [`as_uninit_ref`]. + /// + /// [`as_mut`]: #method.as_mut + /// [`as_uninit_ref`]: #method.as_uninit_ref + /// + /// # Safety + /// + /// When calling this method, you have to ensure that all of the following is true: + /// + /// * The pointer must be properly aligned. + /// + /// * It must be "dereferencable" in the sense defined in [the module documentation]. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, for the duration of this lifetime, the memory the pointer points to must + /// not get accessed (read or written) through any other pointer. + /// + /// This applies even if the result of this method is unused! + /// + /// [the module documentation]: crate::ptr#safety + #[inline] + #[unstable(feature = "ptr_as_uninit", issue = "75402")] + pub unsafe fn as_uninit_mut(&mut self) -> &mut MaybeUninit { + // SAFETY: the caller must guarantee that `self` meets all the + // requirements for a reference. + unsafe { &mut *self.cast().as_ptr() } + } } impl NonNull { @@ -112,29 +176,34 @@ impl NonNull { self.pointer as *mut T } - /// Dereferences the content. + /// Returns a shared reference to the value. If the value may be uninitialized, [`as_uninit_ref`] + /// must be used instead. + /// + /// For the mutable counterpart see [`as_mut`]. /// - /// The resulting lifetime is bound to self so this behaves "as if" - /// it were actually an instance of T that is getting borrowed. If a longer - /// (unbound) lifetime is needed, use `&*my_ptr.as_ptr()`. + /// [`as_uninit_ref`]: #method.as_uninit_ref + /// [`as_mut`]: #method.as_mut /// /// # Safety /// /// When calling this method, you have to ensure that all of the following is true: - /// - `self` is properly aligned - /// - `self` must point to an initialized instance of T; in particular, the pointer must be - /// "dereferencable" in the sense defined [here]. + /// + /// * The pointer must be properly aligned. + /// + /// * It must be "dereferencable" in the sense defined in [the module documentation]. + /// + /// * The pointer must point to an initialized instance of `T`. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, for the duration of this lifetime, the memory the pointer points to must + /// not get mutated (except inside `UnsafeCell`). /// /// This applies even if the result of this method is unused! /// (The part about being initialized is not yet fully decided, but until /// it is, the only safe approach is to ensure that they are indeed initialized.) /// - /// Additionally, the lifetime of `self` does not necessarily reflect the actual - /// lifetime of the data. *You* must enforce Rust's aliasing rules. In particular, - /// for the duration of this lifetime, the memory the pointer points to must not - /// get mutated (except inside `UnsafeCell`). - /// - /// [here]: crate::ptr#safety + /// [the module documentation]: crate::ptr#safety #[stable(feature = "nonnull", since = "1.25.0")] #[inline] pub unsafe fn as_ref(&self) -> &T { @@ -143,29 +212,34 @@ impl NonNull { unsafe { &*self.as_ptr() } } - /// Mutably dereferences the content. + /// Returns a unique reference to the value. If the value may be uninitialized, [`as_uninit_mut`] + /// must be used instead. + /// + /// For the shared counterpart see [`as_ref`]. /// - /// The resulting lifetime is bound to self so this behaves "as if" - /// it were actually an instance of T that is getting borrowed. If a longer - /// (unbound) lifetime is needed, use `&mut *my_ptr.as_ptr()`. + /// [`as_uninit_mut`]: #method.as_uninit_mut + /// [`as_ref`]: #method.as_ref /// /// # Safety /// /// When calling this method, you have to ensure that all of the following is true: - /// - `self` is properly aligned - /// - `self` must point to an initialized instance of T; in particular, the pointer must be - /// "dereferenceable" in the sense defined [here]. + /// + /// * The pointer must be properly aligned. + /// + /// * It must be "dereferencable" in the sense defined in [the module documentation]. + /// + /// * The pointer must point to an initialized instance of `T`. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, for the duration of this lifetime, the memory the pointer points to must + /// not get accessed (read or written) through any other pointer. /// /// This applies even if the result of this method is unused! /// (The part about being initialized is not yet fully decided, but until - /// it is the only safe approach is to ensure that they are indeed initialized.) - /// - /// Additionally, the lifetime of `self` does not necessarily reflect the actual - /// lifetime of the data. *You* must enforce Rust's aliasing rules. In particular, - /// for the duration of this lifetime, the memory this pointer points to must not - /// get accessed (read or written) through any other pointer. + /// it is, the only safe approach is to ensure that they are indeed initialized.) /// - /// [here]: crate::ptr#safety + /// [the module documentation]: crate::ptr#safety #[stable(feature = "nonnull", since = "1.25.0")] #[inline] pub unsafe fn as_mut(&mut self) -> &mut T { @@ -278,6 +352,115 @@ impl NonNull<[T]> { self.as_non_null_ptr().as_ptr() } + /// Returns a shared reference to a slice of possibly uninitialized values. In contrast to + /// [`as_ref`], this does not require that the value has to be initialized. + /// + /// For the mutable counterpart see [`as_uninit_slice_mut`]. + /// + /// [`as_ref`]: #method.as_ref + /// [`as_uninit_slice_mut`]: #method.as_uninit_slice_mut + /// + /// # Safety + /// + /// When calling this method, you have to ensure that all of the following is true: + /// + /// * The pointer must be [valid] for reads for `ptr.len() * mem::size_of::()` many bytes, + /// and it must be properly aligned. This means in particular: + /// + /// * The entire memory range of this slice must be contained within a single allocated object! + /// Slices can never span across multiple allocated objects. + /// + /// * The pointer must be aligned even for zero-length slices. One + /// reason for this is that enum layout optimizations may rely on references + /// (including slices of any length) being aligned and non-null to distinguish + /// them from other data. You can obtain a pointer that is usable as `data` + /// for zero-length slices using [`NonNull::dangling()`]. + /// + /// * The total size `ptr.len() * mem::size_of::()` of the slice must be no larger than `isize::MAX`. + /// See the safety documentation of [`pointer::offset`]. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, for the duration of this lifetime, the memory the pointer points to must + /// not get mutated (except inside `UnsafeCell`). + /// + /// This applies even if the result of this method is unused! + /// + /// See also [`slice::from_raw_parts`][]. + /// + /// [valid]: crate::ptr#safety + /// [`NonNull::dangling()`]: NonNull::dangling + /// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset + #[inline] + #[unstable(feature = "ptr_as_uninit", issue = "75402")] + pub unsafe fn as_uninit_slice(&self) -> &[MaybeUninit] { + // SAFETY: the caller must uphold the safety contract for `as_uninit_slice`. + unsafe { slice::from_raw_parts(self.cast().as_ptr(), self.len()) } + } + + /// Returns a unique reference to a slice of possibly uninitialized values. In contrast to + /// [`as_mut`], this does not require that the value has to be initialized. + /// + /// For the shared counterpart see [`as_uninit_slice`]. + /// + /// [`as_mut`]: #method.as_mut + /// [`as_uninit_slice`]: #method.as_uninit_slice + /// + /// # Safety + /// + /// When calling this method, you have to ensure that all of the following is true: + /// + /// * The pointer must be [valid] for reads and writes for `ptr.len() * mem::size_of::()` + /// many bytes, and it must be properly aligned. This means in particular: + /// + /// * The entire memory range of this slice must be contained within a single allocated object! + /// Slices can never span across multiple allocated objects. + /// + /// * The pointer must be aligned even for zero-length slices. One + /// reason for this is that enum layout optimizations may rely on references + /// (including slices of any length) being aligned and non-null to distinguish + /// them from other data. You can obtain a pointer that is usable as `data` + /// for zero-length slices using [`NonNull::dangling()`]. + /// + /// * The total size `ptr.len() * mem::size_of::()` of the slice must be no larger than `isize::MAX`. + /// See the safety documentation of [`pointer::offset`]. + /// + /// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is + /// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. + /// In particular, for the duration of this lifetime, the memory the pointer points to must + /// not get accessed (read or written) through any other pointer. + /// + /// This applies even if the result of this method is unused! + /// + /// See also [`slice::from_raw_parts_mut`][]. + /// + /// [valid]: crate::ptr#safety + /// [`NonNull::dangling()`]: NonNull::dangling + /// [`pointer::offset`]: ../../std/primitive.pointer.html#method.offset + /// + /// # Examples + /// + /// ```rust + /// #![feature(allocator_api, ptr_as_uninit)] + /// + /// use std::alloc::{AllocRef, Layout, Global}; + /// use std::mem::MaybeUninit; + /// use std::ptr::NonNull; + /// + /// let memory: NonNull<[u8]> = Global.alloc(Layout::new::<[u8; 32]>())?; + /// // This is safe as `memory` is valid for reads and writes for `memory.len()` many bytes. + /// // Note that calling `memory.as_mut()` is not allowed here as the content may be uninitialized. + /// # #[allow(unused_variables)] + /// let slice: &mut [MaybeUninit] = unsafe { memory.as_uninit_slice_mut() }; + /// # Ok::<_, std::alloc::AllocErr>(()) + /// ``` + #[inline] + #[unstable(feature = "ptr_as_uninit", issue = "75402")] + pub unsafe fn as_uninit_slice_mut(&self) -> &mut [MaybeUninit] { + // SAFETY: the caller must uphold the safety contract for `as_uninit_slice_mut`. + unsafe { slice::from_raw_parts_mut(self.cast().as_ptr(), self.len()) } + } + /// Returns a raw pointer to an element or subslice, without doing bounds /// checking. /// From cbc13c5eb72ffd470a3e4a59c96c85e004268584 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 17 Aug 2020 15:14:53 +0200 Subject: [PATCH 07/12] Clean up E0754 explanation --- src/librustc_error_codes/error_codes/E0754.md | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0754.md b/src/librustc_error_codes/error_codes/E0754.md index abdc01ed21ab7..576317e12918c 100644 --- a/src/librustc_error_codes/error_codes/E0754.md +++ b/src/librustc_error_codes/error_codes/E0754.md @@ -1,31 +1,27 @@ An non-ascii identifier was used in an invalid context. -Erroneous code example: +Erroneous code examples: ```compile_fail,E0754 # #![feature(non_ascii_idents)] mod řųśť; // ^ error! -fn main() {} -``` - -```compile_fail,E0754 -# #![feature(non_ascii_idents)] #[no_mangle] fn řųśť() {} // ^ error! + fn main() {} ``` -Non-ascii can be used as module names if it is inline -or a #\[path\] attribute is specified. For example: +Non-ascii can be used as module names if it is inline or a `#[path]` attribute +is specified. For example: ``` # #![feature(non_ascii_idents)] -mod řųśť { +mod řųśť { // ok! const IS_GREAT: bool = true; } From 509cad7f2f8e6c8985b707cab4ab9e1cd78f63c8 Mon Sep 17 00:00:00 2001 From: Ellen Date: Mon, 17 Aug 2020 14:41:57 +0100 Subject: [PATCH 08/12] Switch to intra-doc links for std/src/error.rs --- library/std/src/error.rs | 28 +++------------------------- 1 file changed, 3 insertions(+), 25 deletions(-) diff --git a/library/std/src/error.rs b/library/std/src/error.rs index 3b4cb859dd425..1b7681bd4bb1d 100644 --- a/library/std/src/error.rs +++ b/library/std/src/error.rs @@ -40,10 +40,8 @@ use crate::string; /// provide its own errors while also revealing some of the implementation for /// debugging via [`source`] chains. /// -/// [`Result`]: ../result/enum.Result.html -/// [`Display`]: ../fmt/trait.Display.html -/// [`Debug`]: ../fmt/trait.Debug.html -/// [`source`]: trait.Error.html#method.source +/// [`Result`]: Result +/// [`source`]: Error::source #[stable(feature = "rust1", since = "1.0.0")] pub trait Error: Debug + Display { /// The lower-level source of this error, if any. @@ -164,8 +162,6 @@ mod private { impl<'a, E: Error + 'a> From for Box { /// Converts a type of [`Error`] into a box of dyn [`Error`]. /// - /// [`Error`]: ../error/trait.Error.html - /// /// # Examples /// /// ``` @@ -199,8 +195,6 @@ impl<'a, E: Error + Send + Sync + 'a> From for Box From for Box for Box { /// Converts a [`String`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// - /// [`Error`]: ../error/trait.Error.html - /// /// # Examples /// /// ``` @@ -283,8 +275,6 @@ impl From for Box { impl From for Box { /// Converts a [`String`] into a box of dyn [`Error`]. /// - /// [`Error`]: ../error/trait.Error.html - /// /// # Examples /// /// ``` @@ -306,8 +296,6 @@ impl From for Box { impl<'a> From<&str> for Box { /// Converts a [`str`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// - /// [`Error`]: ../error/trait.Error.html - /// /// # Examples /// /// ``` @@ -329,8 +317,6 @@ impl<'a> From<&str> for Box { impl From<&str> for Box { /// Converts a [`str`] into a box of dyn [`Error`]. /// - /// [`Error`]: ../error/trait.Error.html - /// /// # Examples /// /// ``` @@ -350,9 +336,6 @@ impl From<&str> for Box { impl<'a, 'b> From> for Box { /// Converts a [`Cow`] into a box of dyn [`Error`] + [`Send`] + [`Sync`]. /// - /// [`Cow`]: ../borrow/enum.Cow.html - /// [`Error`]: ../error/trait.Error.html - /// /// # Examples /// /// ``` @@ -374,9 +357,6 @@ impl<'a, 'b> From> for Box { impl<'a> From> for Box { /// Converts a [`Cow`] into a box of dyn [`Error`]. /// - /// [`Cow`]: ../borrow/enum.Cow.html - /// [`Error`]: ../error/trait.Error.html - /// /// # Examples /// /// ``` @@ -703,7 +683,7 @@ impl dyn Error { /// assert!(iter.next().is_none()); /// ``` /// - /// [`source`]: trait.Error.html#method.source + /// [`source`]: Error::source #[unstable(feature = "error_iter", issue = "58520")] #[inline] pub fn chain(&self) -> Chain<'_> { @@ -715,8 +695,6 @@ impl dyn Error { /// /// If you want to omit the initial error and only process /// its sources, use `skip(1)`. -/// -/// [`Error`]: trait.Error.html #[unstable(feature = "error_iter", issue = "58520")] #[derive(Clone, Debug)] pub struct Chain<'a> { From b6d2868caa63aa7bc8d54812cff06972eb558171 Mon Sep 17 00:00:00 2001 From: Ellen Date: Mon, 17 Aug 2020 14:42:23 +0100 Subject: [PATCH 09/12] Switch to intra-doc links for std/src/env.rs --- library/std/src/env.rs | 41 ++++++++++++++--------------------------- 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 6489e0709cb91..562fdfc689a86 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -7,9 +7,6 @@ //! There are several functions and structs in this module that have a //! counterpart ending in `os`. Those ending in `os` will return an [`OsString`] //! and those without will return a [`String`]. -//! -//! [`OsString`]: ../../std/ffi/struct.OsString.html -//! [`String`]: ../string/struct.String.html #![stable(feature = "env", since = "1.0.0")] @@ -31,8 +28,7 @@ use crate::sys::os as os_imp; /// * Current directory does not exist. /// * There are insufficient permissions to access the current directory. /// -/// [`PathBuf`]: ../../std/path/struct.PathBuf.html -/// [`Err`]: ../../std/result/enum.Result.html#method.err +/// [`Err`]: Result::Err /// /// # Examples /// @@ -54,7 +50,7 @@ pub fn current_dir() -> io::Result { /// /// Returns an [`Err`] if the operation fails. /// -/// [`Err`]: ../../std/result/enum.Result.html#method.err +/// [`Err`]: Result::Err /// /// # Examples /// @@ -76,7 +72,7 @@ pub fn set_current_dir>(path: P) -> io::Result<()> { /// This structure is created by the [`std::env::vars`] function. See its /// documentation for more. /// -/// [`std::env::vars`]: fn.vars.html +/// [`std::env::vars`]: vars #[stable(feature = "env", since = "1.0.0")] pub struct Vars { inner: VarsOs, @@ -87,7 +83,7 @@ pub struct Vars { /// This structure is created by the [`std::env::vars_os`] function. See /// its documentation for more. /// -/// [`std::env::vars_os`]: fn.vars_os.html +/// [`std::env::vars_os`]: vars_os #[stable(feature = "env", since = "1.0.0")] pub struct VarsOs { inner: os_imp::Env, @@ -106,7 +102,7 @@ pub struct VarsOs { /// environment is not valid unicode. If this is not desired, consider using the /// [`env::vars_os`] function. /// -/// [`env::vars_os`]: fn.vars_os.html +/// [`env::vars_os`]: vars_os /// /// # Examples /// @@ -222,7 +218,7 @@ fn _var(key: &OsStr) -> Result { /// Fetches the environment variable `key` from the current process, returning /// [`None`] if the variable isn't set. /// -/// [`None`]: ../option/enum.Option.html#variant.None +/// [`None`]: Option::None /// /// # Panics /// @@ -254,7 +250,7 @@ fn _var_os(key: &OsStr) -> Option { /// The error type for operations interacting with environment variables. /// Possibly returned from the [`env::var`] function. /// -/// [`env::var`]: fn.var.html +/// [`env::var`]: var #[derive(Debug, PartialEq, Eq, Clone)] #[stable(feature = "env", since = "1.0.0")] pub enum VarError { @@ -382,8 +378,7 @@ fn _remove_var(k: &OsStr) { /// This structure is created by the [`std::env::split_paths`] function. See its /// documentation for more. /// -/// [`PathBuf`]: ../../std/path/struct.PathBuf.html -/// [`std::env::split_paths`]: fn.split_paths.html +/// [`std::env::split_paths`]: split_paths #[stable(feature = "env", since = "1.0.0")] pub struct SplitPaths<'a> { inner: os_imp::SplitPaths<'a>, @@ -410,8 +405,6 @@ pub struct SplitPaths<'a> { /// None => println!("{} is not defined in the environment.", key) /// } /// ``` -/// -/// [`PathBuf`]: ../../std/path/struct.PathBuf.html #[stable(feature = "env", since = "1.0.0")] pub fn split_paths + ?Sized>(unparsed: &T) -> SplitPaths<'_> { SplitPaths { inner: os_imp::split_paths(unparsed.as_ref()) } @@ -438,7 +431,7 @@ impl fmt::Debug for SplitPaths<'_> { /// The error type for operations on the `PATH` variable. Possibly returned from /// the [`env::join_paths`] function. /// -/// [`env::join_paths`]: fn.join_paths.html +/// [`env::join_paths`]: join_paths #[derive(Debug)] #[stable(feature = "env", since = "1.0.0")] pub struct JoinPathsError { @@ -450,13 +443,11 @@ pub struct JoinPathsError { /// /// # Errors /// -/// Returns an [`Err`][err] (containing an error message) if one of the input +/// Returns an [`Err`] (containing an error message) if one of the input /// [`Path`]s contains an invalid character for constructing the `PATH` /// variable (a double quote on Windows or a colon on Unix). /// -/// [`Path`]: ../../std/path/struct.Path.html -/// [`OsString`]: ../../std/ffi/struct.OsString.html -/// [err]: ../../std/result/enum.Result.html#variant.Err +/// [Err]: Result::Err /// /// # Examples /// @@ -508,7 +499,7 @@ pub struct JoinPathsError { /// } /// ``` /// -/// [`env::split_paths`]: fn.split_paths.html +/// [`env::split_paths`]: split_paths #[stable(feature = "env", since = "1.0.0")] pub fn join_paths(paths: I) -> Result where @@ -688,8 +679,7 @@ pub fn current_exe() -> io::Result { /// set to arbitrary text, and may not even exist. This means this property /// should not be relied upon for security purposes. /// -/// [`String`]: ../string/struct.String.html -/// [`std::env::args`]: ./fn.args.html +/// [`std::env::args`]: args #[stable(feature = "env", since = "1.0.0")] pub struct Args { inner: ArgsOs, @@ -705,8 +695,7 @@ pub struct Args { /// set to arbitrary text, and may not even exist. This means this property /// should not be relied upon for security purposes. /// -/// [`OsString`]: ../ffi/struct.OsString.html -/// [`std::env::args_os`]: ./fn.args_os.html +/// [`std::env::args_os`]: args_os #[stable(feature = "env", since = "1.0.0")] pub struct ArgsOs { inner: sys::args::Args, @@ -744,8 +733,6 @@ pub struct ArgsOs { /// println!("{}", argument); /// } /// ``` -/// -/// [`args_os`]: ./fn.args_os.html #[stable(feature = "env", since = "1.0.0")] pub fn args() -> Args { Args { inner: args_os() } From a2dfc3ec78b0832f0b6446a628c905fe4b09fd60 Mon Sep 17 00:00:00 2001 From: Ellen Date: Mon, 17 Aug 2020 14:42:40 +0100 Subject: [PATCH 10/12] Switch to intra-doc links for std/src/alloc.rs --- library/std/src/alloc.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index 4712cc95b4ab7..37a8f514aa157 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -7,8 +7,6 @@ //! like `cdylib`s and `staticlib`s are guaranteed to use the [`System`] by //! default. //! -//! [`System`]: struct.System.html -//! //! # The `#[global_allocator]` attribute //! //! This attribute allows configuring the choice of global allocator. @@ -43,8 +41,6 @@ //! The attribute is used on a `static` item whose type implements the //! [`GlobalAlloc`] trait. This type can be provided by an external library: //! -//! [`GlobalAlloc`]: ../../core/alloc/trait.GlobalAlloc.html -//! //! ```rust,ignore (demonstrates crates.io usage) //! extern crate jemallocator; //! @@ -284,9 +280,6 @@ static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut()); /// about the allocation that failed. /// /// The allocation error hook is a global resource. -/// -/// [`set_alloc_error_hook`]: fn.set_alloc_error_hook.html -/// [`take_alloc_error_hook`]: fn.take_alloc_error_hook.html #[unstable(feature = "alloc_error_hook", issue = "51245")] pub fn set_alloc_error_hook(hook: fn(Layout)) { HOOK.store(hook as *mut (), Ordering::SeqCst); @@ -297,8 +290,6 @@ pub fn set_alloc_error_hook(hook: fn(Layout)) { /// *See also the function [`set_alloc_error_hook`].* /// /// If no custom hook is registered, the default hook will be returned. -/// -/// [`set_alloc_error_hook`]: fn.set_alloc_error_hook.html #[unstable(feature = "alloc_error_hook", issue = "51245")] pub fn take_alloc_error_hook() -> fn(Layout) { let hook = HOOK.swap(ptr::null_mut(), Ordering::SeqCst); From e7a72797506448b7525c963af2967356958f7e9b Mon Sep 17 00:00:00 2001 From: Ellen Date: Mon, 17 Aug 2020 15:16:00 +0100 Subject: [PATCH 11/12] Remove unnecessary links in env.rs --- library/std/src/env.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 562fdfc689a86..387c588f4a061 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -28,8 +28,6 @@ use crate::sys::os as os_imp; /// * Current directory does not exist. /// * There are insufficient permissions to access the current directory. /// -/// [`Err`]: Result::Err -/// /// # Examples /// /// ``` @@ -50,8 +48,6 @@ pub fn current_dir() -> io::Result { /// /// Returns an [`Err`] if the operation fails. /// -/// [`Err`]: Result::Err -/// /// # Examples /// /// ``` @@ -218,8 +214,6 @@ fn _var(key: &OsStr) -> Result { /// Fetches the environment variable `key` from the current process, returning /// [`None`] if the variable isn't set. /// -/// [`None`]: Option::None -/// /// # Panics /// /// This function may panic if `key` is empty, contains an ASCII equals sign @@ -447,8 +441,6 @@ pub struct JoinPathsError { /// [`Path`]s contains an invalid character for constructing the `PATH` /// variable (a double quote on Windows or a colon on Unix). /// -/// [Err]: Result::Err -/// /// # Examples /// /// Joining paths on a Unix-like platform: From 4fa69cb3ce468c94e8f1c5927212270e9bc74884 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 17 Aug 2020 17:22:53 +0200 Subject: [PATCH 12/12] Improve display --- src/librustc_error_codes/error_codes/E0754.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0754.md b/src/librustc_error_codes/error_codes/E0754.md index 576317e12918c..57620bcd65c18 100644 --- a/src/librustc_error_codes/error_codes/E0754.md +++ b/src/librustc_error_codes/error_codes/E0754.md @@ -5,18 +5,16 @@ Erroneous code examples: ```compile_fail,E0754 # #![feature(non_ascii_idents)] -mod řųśť; -// ^ error! +mod řųśť; // error! #[no_mangle] -fn řųśť() {} -// ^ error! +fn řųśť() {} // error! fn main() {} ``` -Non-ascii can be used as module names if it is inline or a `#[path]` attribute -is specified. For example: +Non-ascii can be used as module names if it is inlined or if a `#[path]` +attribute is specified. For example: ``` # #![feature(non_ascii_idents)]