Skip to content

Commit c6ceb5b

Browse files
authored
Rollup merge of #128157 - lolbinarycat:unify-ptr-ref-docs, r=cuviper
deduplicate and clarify rules for converting pointers to references part of #124669
2 parents 110c3df + b11e0a8 commit c6ceb5b

File tree

4 files changed

+73
-210
lines changed

4 files changed

+73
-210
lines changed

library/core/src/ptr/const_ptr.rs

+4-50
Original file line numberDiff line numberDiff line change
@@ -239,24 +239,7 @@ impl<T: ?Sized> *const T {
239239
/// # Safety
240240
///
241241
/// When calling this method, you have to ensure that *either* the pointer is null *or*
242-
/// all of the following is true:
243-
///
244-
/// * The pointer must be properly aligned.
245-
///
246-
/// * It must be "dereferenceable" in the sense defined in [the module documentation].
247-
///
248-
/// * The pointer must point to an initialized instance of `T`.
249-
///
250-
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
251-
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
252-
/// In particular, while this reference exists, the memory the pointer points to must
253-
/// not get mutated (except inside `UnsafeCell`).
254-
///
255-
/// This applies even if the result of this method is unused!
256-
/// (The part about being initialized is not yet fully decided, but until
257-
/// it is, the only safe approach is to ensure that they are indeed initialized.)
258-
///
259-
/// [the module documentation]: crate::ptr#safety
242+
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
260243
///
261244
/// # Examples
262245
///
@@ -302,24 +285,8 @@ impl<T: ?Sized> *const T {
302285
///
303286
/// # Safety
304287
///
305-
/// When calling this method, you have to ensure that all of the following is true:
306-
///
307-
/// * The pointer must be properly aligned.
308-
///
309-
/// * It must be "dereferenceable" in the sense defined in [the module documentation].
310-
///
311-
/// * The pointer must point to an initialized instance of `T`.
312-
///
313-
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
314-
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
315-
/// In particular, while this reference exists, the memory the pointer points to must
316-
/// not get mutated (except inside `UnsafeCell`).
317-
///
318-
/// This applies even if the result of this method is unused!
319-
/// (The part about being initialized is not yet fully decided, but until
320-
/// it is, the only safe approach is to ensure that they are indeed initialized.)
321-
///
322-
/// [the module documentation]: crate::ptr#safety
288+
/// When calling this method, you have to ensure that
289+
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
323290
///
324291
/// # Examples
325292
///
@@ -350,20 +317,7 @@ impl<T: ?Sized> *const T {
350317
/// # Safety
351318
///
352319
/// When calling this method, you have to ensure that *either* the pointer is null *or*
353-
/// all of the following is true:
354-
///
355-
/// * The pointer must be properly aligned.
356-
///
357-
/// * It must be "dereferenceable" in the sense defined in [the module documentation].
358-
///
359-
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
360-
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
361-
/// In particular, while this reference exists, the memory the pointer points to must
362-
/// not get mutated (except inside `UnsafeCell`).
363-
///
364-
/// This applies even if the result of this method is unused!
365-
///
366-
/// [the module documentation]: crate::ptr#safety
320+
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
367321
///
368322
/// # Examples
369323
///

library/core/src/ptr/mod.rs

+46
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,52 @@
5656
//! has size 0, i.e., even if memory is not actually touched. Consider using
5757
//! [`NonNull::dangling`] in such cases.
5858
//!
59+
//! ## Pointer to reference conversion
60+
//! When converting a pointer to a reference `&T` using `&*`,
61+
//! there are several rules that must be followed:
62+
//!
63+
//! * The pointer must be properly aligned.
64+
//!
65+
// some microprocessors may use address 0 for an interrupt vector.
66+
// users of these microprocessors must always read/write address 0 through
67+
// a raw pointer, not a reference.
68+
//! * It must be non-null.
69+
//!
70+
//! * It must be "dereferenceable" in the sense defined above.
71+
//!
72+
//! * The pointer must point to a valid value of type `T`.
73+
//! This means that the created reference can only refer to
74+
//! uninitialized memory through careful use of `MaybeUninit`,
75+
//! or if the uninitialized memory is entirely contained within
76+
//! padding bytes, since
77+
//! [padding has the same validity invariant as `MaybeUninit`][ucg-pad].
78+
//!
79+
//! * You must enforce Rust's aliasing rules, since the lifetime of the
80+
//! created reference is arbitrarily chosen,
81+
//! and does not necessarily reflect the actual lifetime of the data.
82+
//! In particular, while this reference exists,
83+
//! the memory the pointer points to must
84+
//! not get accessed (read or written) through any raw pointer,
85+
//! except for data inside an `UnsafeCell`.
86+
//! Note that aliased writes are always UB for mutable references,
87+
//! even if they only modify `UnsafeCell` data.
88+
//!
89+
//! If a pointer follows all of these rules, it is said to be
90+
//! *convertible to a reference*.
91+
// ^ we use this term instead of saying that the produced reference must
92+
// be valid, as the validity of a reference is easily confused for the
93+
// validity of the thing it refers to, and while the two concepts are
94+
// closly related, they are not identical.
95+
//!
96+
//! These apply even if the result is unused!
97+
//! (The part about being initialized is not yet fully decided, but until
98+
//! it is, the only safe approach is to ensure that they are indeed initialized.)
99+
//!
100+
//! An example of the implications of the above rules is that an expression such
101+
//! as `unsafe { &*(0 as *const u8) }` is Immediate Undefined Behavior.
102+
//!
103+
//! [ucgpad]: https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#padding
104+
//!
59105
//! ## Allocated object
60106
//!
61107
//! An *allocated object* is a subset of program memory which is addressable

library/core/src/ptr/mut_ptr.rs

+11-100
Original file line numberDiff line numberDiff line change
@@ -247,24 +247,7 @@ impl<T: ?Sized> *mut T {
247247
/// # Safety
248248
///
249249
/// When calling this method, you have to ensure that *either* the pointer is null *or*
250-
/// all of the following is true:
251-
///
252-
/// * The pointer must be properly aligned.
253-
///
254-
/// * It must be "dereferenceable" in the sense defined in [the module documentation].
255-
///
256-
/// * The pointer must point to an initialized instance of `T`.
257-
///
258-
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
259-
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
260-
/// In particular, while this reference exists, the memory the pointer points to must
261-
/// not get mutated (except inside `UnsafeCell`).
262-
///
263-
/// This applies even if the result of this method is unused!
264-
/// (The part about being initialized is not yet fully decided, but until
265-
/// it is, the only safe approach is to ensure that they are indeed initialized.)
266-
///
267-
/// [the module documentation]: crate::ptr#safety
250+
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
268251
///
269252
/// # Examples
270253
///
@@ -313,24 +296,7 @@ impl<T: ?Sized> *mut T {
313296
///
314297
/// # Safety
315298
///
316-
/// When calling this method, you have to ensure that all of the following is true:
317-
///
318-
/// * The pointer must be properly aligned.
319-
///
320-
/// * It must be "dereferenceable" in the sense defined in [the module documentation].
321-
///
322-
/// * The pointer must point to an initialized instance of `T`.
323-
///
324-
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
325-
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
326-
/// In particular, while this reference exists, the memory the pointer points to must
327-
/// not get mutated (except inside `UnsafeCell`).
328-
///
329-
/// This applies even if the result of this method is unused!
330-
/// (The part about being initialized is not yet fully decided, but until
331-
/// it is, the only safe approach is to ensure that they are indeed initialized.)
332-
///
333-
/// [the module documentation]: crate::ptr#safety
299+
/// When calling this method, you have to ensure that the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
334300
///
335301
/// # Examples
336302
///
@@ -364,20 +330,9 @@ impl<T: ?Sized> *mut T {
364330
/// # Safety
365331
///
366332
/// When calling this method, you have to ensure that *either* the pointer is null *or*
367-
/// all of the following is true:
368-
///
369-
/// * The pointer must be properly aligned.
370-
///
371-
/// * It must be "dereferenceable" in the sense defined in [the module documentation].
372-
///
373-
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
374-
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
375-
/// In particular, while this reference exists, the memory the pointer points to must
376-
/// not get mutated (except inside `UnsafeCell`).
377-
///
378-
/// This applies even if the result of this method is unused!
379-
///
380-
/// [the module documentation]: crate::ptr#safety
333+
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
334+
/// Note that because the created reference is to `MaybeUninit<T>`, the
335+
/// source pointer can point to uninitialized memory.
381336
///
382337
/// # Examples
383338
///
@@ -609,25 +564,10 @@ impl<T: ?Sized> *mut T {
609564
///
610565
/// # Safety
611566
///
612-
/// When calling this method, you have to ensure that *either* the pointer is null *or*
613-
/// all of the following is true:
614-
///
615-
/// * The pointer must be properly aligned.
616-
///
617-
/// * It must be "dereferenceable" in the sense defined in [the module documentation].
618-
///
619-
/// * The pointer must point to an initialized instance of `T`.
567+
/// When calling this method, you have to ensure that *either*
568+
/// the pointer is null *or*
569+
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
620570
///
621-
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
622-
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
623-
/// In particular, while this reference exists, the memory the pointer points to must
624-
/// not get accessed (read or written) through any other pointer.
625-
///
626-
/// This applies even if the result of this method is unused!
627-
/// (The part about being initialized is not yet fully decided, but until
628-
/// it is, the only safe approach is to ensure that they are indeed initialized.)
629-
///
630-
/// [the module documentation]: crate::ptr#safety
631571
///
632572
/// # Examples
633573
///
@@ -675,24 +615,8 @@ impl<T: ?Sized> *mut T {
675615
///
676616
/// # Safety
677617
///
678-
/// When calling this method, you have to ensure that all of the following is true:
679-
///
680-
/// * The pointer must be properly aligned.
681-
///
682-
/// * It must be "dereferenceable" in the sense defined in [the module documentation].
683-
///
684-
/// * The pointer must point to an initialized instance of `T`.
685-
///
686-
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
687-
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
688-
/// In particular, while this reference exists, the memory the pointer points to must
689-
/// not get mutated (except inside `UnsafeCell`).
690-
///
691-
/// This applies even if the result of this method is unused!
692-
/// (The part about being initialized is not yet fully decided, but until
693-
/// it is, the only safe approach is to ensure that they are indeed initialized.)
694-
///
695-
/// [the module documentation]: crate::ptr#safety
618+
/// When calling this method, you have to ensure that
619+
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
696620
///
697621
/// # Examples
698622
///
@@ -727,20 +651,7 @@ impl<T: ?Sized> *mut T {
727651
/// # Safety
728652
///
729653
/// When calling this method, you have to ensure that *either* the pointer is null *or*
730-
/// all of the following is true:
731-
///
732-
/// * The pointer must be properly aligned.
733-
///
734-
/// * It must be "dereferenceable" in the sense defined in [the module documentation].
735-
///
736-
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
737-
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
738-
/// In particular, while this reference exists, the memory the pointer points to must
739-
/// not get accessed (read or written) through any other pointer.
740-
///
741-
/// This applies even if the result of this method is unused!
742-
///
743-
/// [the module documentation]: crate::ptr#safety
654+
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
744655
#[inline]
745656
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
746657
#[rustc_const_unstable(feature = "const_ptr_as_ref", issue = "91822")]

library/core/src/ptr/non_null.rs

+12-60
Original file line numberDiff line numberDiff line change
@@ -126,20 +126,10 @@ impl<T: Sized> NonNull<T> {
126126
///
127127
/// # Safety
128128
///
129-
/// When calling this method, you have to ensure that all of the following is true:
130-
///
131-
/// * The pointer must be properly aligned.
132-
///
133-
/// * It must be "dereferenceable" in the sense defined in [the module documentation].
134-
///
135-
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
136-
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
137-
/// In particular, while this reference exists, the memory the pointer points to must
138-
/// not get mutated (except inside `UnsafeCell`).
139-
///
140-
/// This applies even if the result of this method is unused!
141-
///
142-
/// [the module documentation]: crate::ptr#safety
129+
/// When calling this method, you have to ensure that
130+
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
131+
/// Note that because the created reference is to `MaybeUninit<T>`, the
132+
/// source pointer can point to uninitialized memory.
143133
#[inline]
144134
#[must_use]
145135
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
@@ -160,20 +150,10 @@ impl<T: Sized> NonNull<T> {
160150
///
161151
/// # Safety
162152
///
163-
/// When calling this method, you have to ensure that all of the following is true:
164-
///
165-
/// * The pointer must be properly aligned.
166-
///
167-
/// * It must be "dereferenceable" in the sense defined in [the module documentation].
168-
///
169-
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
170-
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
171-
/// In particular, while this reference exists, the memory the pointer points to must
172-
/// not get accessed (read or written) through any other pointer.
173-
///
174-
/// This applies even if the result of this method is unused!
175-
///
176-
/// [the module documentation]: crate::ptr#safety
153+
/// When calling this method, you have to ensure that
154+
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
155+
/// Note that because the created reference is to `MaybeUninit<T>`, the
156+
/// source pointer can point to uninitialized memory.
177157
#[inline]
178158
#[must_use]
179159
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
@@ -359,22 +339,8 @@ impl<T: ?Sized> NonNull<T> {
359339
///
360340
/// # Safety
361341
///
362-
/// When calling this method, you have to ensure that all of the following is true:
363-
///
364-
/// * The pointer must be properly aligned.
365-
///
366-
/// * It must be "dereferenceable" in the sense defined in [the module documentation].
367-
///
368-
/// * The pointer must point to an initialized instance of `T`.
369-
///
370-
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
371-
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
372-
/// In particular, while this reference exists, the memory the pointer points to must
373-
/// not get mutated (except inside `UnsafeCell`).
374-
///
375-
/// This applies even if the result of this method is unused!
376-
/// (The part about being initialized is not yet fully decided, but until
377-
/// it is, the only safe approach is to ensure that they are indeed initialized.)
342+
/// When calling this method, you have to ensure that
343+
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
378344
///
379345
/// # Examples
380346
///
@@ -410,22 +376,8 @@ impl<T: ?Sized> NonNull<T> {
410376
///
411377
/// # Safety
412378
///
413-
/// When calling this method, you have to ensure that all of the following is true:
414-
///
415-
/// * The pointer must be properly aligned.
416-
///
417-
/// * It must be "dereferenceable" in the sense defined in [the module documentation].
418-
///
419-
/// * The pointer must point to an initialized instance of `T`.
420-
///
421-
/// * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
422-
/// arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
423-
/// In particular, while this reference exists, the memory the pointer points to must
424-
/// not get accessed (read or written) through any other pointer.
425-
///
426-
/// This applies even if the result of this method is unused!
427-
/// (The part about being initialized is not yet fully decided, but until
428-
/// it is, the only safe approach is to ensure that they are indeed initialized.)
379+
/// When calling this method, you have to ensure that
380+
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
429381
/// # Examples
430382
///
431383
/// ```

0 commit comments

Comments
 (0)