From 57e0dea178eba21de2b001f731aeb95692ee84b9 Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Sun, 28 Jan 2024 15:39:19 +0100 Subject: [PATCH 1/6] Document requirements for unsized {Rc,Arc}::from_raw --- library/alloc/src/rc.rs | 20 ++++++++++++++------ library/alloc/src/sync.rs | 20 ++++++++++++++------ 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 7705c86001e64..5e85746656ece 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1181,12 +1181,19 @@ impl Rc { /// Constructs an `Rc` from a raw pointer. /// /// The raw pointer must have been previously returned by a call to - /// [`Rc::into_raw`][into_raw] where `U` must have the same size - /// and alignment as `T`. This is trivially true if `U` is `T`. - /// Note that if `U` is not `T` but has the same size and alignment, this is - /// basically like transmuting references of different types. See - /// [`mem::transmute`][transmute] for more information on what - /// restrictions apply in this case. + /// [`Rc::into_raw`][into_raw] with the following requirements: + /// + /// * If `U` is sized, it must have the same size and alignment as `T`. This + /// is trivially true if `U` is `T`. + /// * If `U` is unsized, its data pointer must have the same size and + /// alignment as `T`. This is trivially true if `Arc` was constructed + /// through `Arc` and then converted to `Arc` through an [unsized + /// coercion]. + /// + /// Note that if `U` or `U`'s data pointer is not `T` but has the same size + /// and alignment, this is basically like transmuting references of + /// different types. See [`mem::transmute`][transmute] for more information + /// on what restrictions apply in this case. /// /// The raw pointer must point to a block of memory allocated by the global allocator /// @@ -1198,6 +1205,7 @@ impl Rc { /// /// [into_raw]: Rc::into_raw /// [transmute]: core::mem::transmute + /// [unsized coercion]: https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions /// /// # Examples /// diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 48c8d9d113b06..95cf2da0ecf7f 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1329,12 +1329,19 @@ impl Arc { /// Constructs an `Arc` from a raw pointer. /// /// The raw pointer must have been previously returned by a call to - /// [`Arc::into_raw`][into_raw] where `U` must have the same size and - /// alignment as `T`. This is trivially true if `U` is `T`. - /// Note that if `U` is not `T` but has the same size and alignment, this is - /// basically like transmuting references of different types. See - /// [`mem::transmute`][transmute] for more information on what - /// restrictions apply in this case. + /// [`Arc::into_raw`][into_raw] with the following requirements: + /// + /// * If `U` is sized, it must have the same size and alignment as `T`. This + /// is trivially true if `U` is `T`. + /// * If `U` is unsized, its data pointer must have the same size and + /// alignment as `T`. This is trivially true if `Arc` was constructed + /// through `Arc` and then converted to `Arc` through an [unsized + /// coercion]. + /// + /// Note that if `U` or `U`'s data pointer is not `T` but has the same size + /// and alignment, this is basically like transmuting references of + /// different types. See [`mem::transmute`][transmute] for more information + /// on what restrictions apply in this case. /// /// The user of `from_raw` has to make sure a specific value of `T` is only /// dropped once. @@ -1344,6 +1351,7 @@ impl Arc { /// /// [into_raw]: Arc::into_raw /// [transmute]: core::mem::transmute + /// [unsized coercion]: https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions /// /// # Examples /// From d4adb3af585daac5077c8852bc0b26bb661330c8 Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Sun, 28 Jan 2024 16:07:07 +0100 Subject: [PATCH 2/6] Add examples for unsized {Rc,Arc}::from_raw --- library/alloc/src/rc.rs | 14 ++++++++++++++ library/alloc/src/sync.rs | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 5e85746656ece..0a959738b97e3 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1225,6 +1225,20 @@ impl Rc { /// /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! /// ``` + /// + /// Convert a slice back into its original array: + /// + /// ``` + /// use std::rc::Rc; + /// + /// let x: Rc<[u32]> = Rc::new([1, 2, 3]); + /// let x_ptr: *const [u32] = Rc::into_raw(x); + /// + /// unsafe { + /// let x: Rc<[u32; 3]> = Rc::from_raw(x_ptr.cast::<[u32; 3]>()) + /// assert_eq!(x.as_ref(), &[1, 2, 3]); + /// } + /// ``` #[inline] #[stable(feature = "rc_raw", since = "1.17.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 95cf2da0ecf7f..708f11edc448d 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1371,6 +1371,20 @@ impl Arc { /// /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! /// ``` + /// + /// Convert a slice back into its original array: + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x: Arc<[u32]> = Arc::new([1, 2, 3]); + /// let x_ptr: *const [u32] = Arc::into_raw(x); + /// + /// unsafe { + /// let x: Arc<[u32; 3]> = Arc::from_raw(x_ptr.cast::<[u32; 3]>()) + /// assert_eq!(x.as_ref(), &[1, 2, 3]); + /// } + /// ``` #[inline] #[stable(feature = "rc_raw", since = "1.17.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { From 23c83fab2b16d79b248b1b5f2faf7b538afec9f6 Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Sun, 28 Jan 2024 16:12:09 +0100 Subject: [PATCH 3/6] Tidy up --- library/alloc/src/rc.rs | 2 +- library/alloc/src/sync.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 0a959738b97e3..1d16095db1e40 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1182,7 +1182,7 @@ impl Rc { /// /// The raw pointer must have been previously returned by a call to /// [`Rc::into_raw`][into_raw] with the following requirements: - /// + /// /// * If `U` is sized, it must have the same size and alignment as `T`. This /// is trivially true if `U` is `T`. /// * If `U` is unsized, its data pointer must have the same size and diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 708f11edc448d..0487dc5a8583f 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1330,7 +1330,7 @@ impl Arc { /// /// The raw pointer must have been previously returned by a call to /// [`Arc::into_raw`][into_raw] with the following requirements: - /// + /// /// * If `U` is sized, it must have the same size and alignment as `T`. This /// is trivially true if `U` is `T`. /// * If `U` is unsized, its data pointer must have the same size and From d63384d689ef9dab759eee57e3c2b0f82dfef4e3 Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Sun, 28 Jan 2024 16:38:38 +0100 Subject: [PATCH 4/6] Fix doctest --- library/alloc/src/rc.rs | 4 ++-- library/alloc/src/sync.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 1d16095db1e40..8331a2d63a018 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1235,8 +1235,8 @@ impl Rc { /// let x_ptr: *const [u32] = Rc::into_raw(x); /// /// unsafe { - /// let x: Rc<[u32; 3]> = Rc::from_raw(x_ptr.cast::<[u32; 3]>()) - /// assert_eq!(x.as_ref(), &[1, 2, 3]); + /// let x: Rc<[u32; 3]> = Rc::from_raw(x_ptr.cast::<[u32; 3]>()); + /// assert_eq!(&*x, &[1, 2, 3]); /// } /// ``` #[inline] diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 0487dc5a8583f..bfbdfce571862 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1381,8 +1381,8 @@ impl Arc { /// let x_ptr: *const [u32] = Arc::into_raw(x); /// /// unsafe { - /// let x: Arc<[u32; 3]> = Arc::from_raw(x_ptr.cast::<[u32; 3]>()) - /// assert_eq!(x.as_ref(), &[1, 2, 3]); + /// let x: Arc<[u32; 3]> = Arc::from_raw(x_ptr.cast::<[u32; 3]>()); + /// assert_eq!(&*x, &[1, 2, 3]); /// } /// ``` #[inline] From eebc7207579d06ccdb38bd79c01bec08f1c29bde Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Sun, 28 Jan 2024 17:00:13 +0100 Subject: [PATCH 5/6] Replicate documentation in {Rc,Arc}::from_raw_in --- library/alloc/src/rc.rs | 43 +++++++++++++++++++++++++++++++-------- library/alloc/src/sync.rs | 39 ++++++++++++++++++++++++++++------- 2 files changed, 66 insertions(+), 16 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 8331a2d63a018..ebd816fba813b 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1186,8 +1186,8 @@ impl Rc { /// * If `U` is sized, it must have the same size and alignment as `T`. This /// is trivially true if `U` is `T`. /// * If `U` is unsized, its data pointer must have the same size and - /// alignment as `T`. This is trivially true if `Arc` was constructed - /// through `Arc` and then converted to `Arc` through an [unsized + /// alignment as `T`. This is trivially true if `Rc` was constructed + /// through `Rc` and then converted to `Rc` through an [unsized /// coercion]. /// /// Note that if `U` or `U`'s data pointer is not `T` but has the same size @@ -1363,13 +1363,20 @@ impl Rc { /// Constructs an `Rc` from a raw pointer in the provided allocator. /// - /// The raw pointer must have been previously returned by a call to - /// [`Rc::into_raw`][into_raw] where `U` must have the same size - /// and alignment as `T`. This is trivially true if `U` is `T`. - /// Note that if `U` is not `T` but has the same size and alignment, this is - /// basically like transmuting references of different types. See - /// [`mem::transmute`] for more information on what - /// restrictions apply in this case. + /// The raw pointer must have been previously returned by a call to [`Rc::into_raw`][into_raw] with the following requirements: + /// + /// * If `U` is sized, it must have the same size and alignment as `T`. This + /// is trivially true if `U` is `T`. + /// * If `U` is unsized, its data pointer must have the same size and + /// alignment as `T`. This is trivially true if `Rc` was constructed + /// through `Rc` and then converted to `Rc` through an [unsized + /// coercion]. + /// + /// Note that if `U` or `U`'s data pointer is not `T` but has the same size + /// and alignment, this is basically like transmuting references of + /// different types. See [`mem::transmute`][transmute] for more information + /// on what restrictions apply in this case. /// /// The raw pointer must point to a block of memory allocated by `alloc` /// @@ -1380,6 +1387,7 @@ impl Rc { /// even if the returned `Rc` is never accessed. /// /// [into_raw]: Rc::into_raw + /// [unsized coercion]: https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions /// /// # Examples /// @@ -1402,6 +1410,23 @@ impl Rc { /// /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! /// ``` + /// + /// Convert a slice back into its original array: + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::rc::Rc; + /// use std::alloc::System; + /// + /// let x: Rc<[u32]> = Rc::new_in([1, 2, 3], System); + /// let x_ptr: *const [u32] = Rc::into_raw(x); + /// + /// unsafe { + /// let x: Rc<[u32; 3]> = Rc::from_raw_in(x_ptr.cast::<[u32; 3]>(), System); + /// assert_eq!(&*x, &[1, 2, 3]); + /// } + /// ``` #[unstable(feature = "allocator_api", issue = "32838")] pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self { let offset = unsafe { data_offset(ptr) }; diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index bfbdfce571862..96f8f57f9e09a 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1514,13 +1514,20 @@ impl Arc { /// Constructs an `Arc` from a raw pointer. /// - /// The raw pointer must have been previously returned by a call to - /// [`Arc::into_raw`][into_raw] where `U` must have the same size and - /// alignment as `T`. This is trivially true if `U` is `T`. - /// Note that if `U` is not `T` but has the same size and alignment, this is - /// basically like transmuting references of different types. See - /// [`mem::transmute`] for more information on what - /// restrictions apply in this case. + /// The raw pointer must have been previously returned by a call to [`Arc::into_raw`][into_raw] with the following requirements: + /// + /// * If `U` is sized, it must have the same size and alignment as `T`. This + /// is trivially true if `U` is `T`. + /// * If `U` is unsized, its data pointer must have the same size and + /// alignment as `T`. This is trivially true if `Arc` was constructed + /// through `Arc` and then converted to `Arc` through an [unsized + /// coercion]. + /// + /// Note that if `U` or `U`'s data pointer is not `T` but has the same size + /// and alignment, this is basically like transmuting references of + /// different types. See [`mem::transmute`][transmute] for more information + /// on what restrictions apply in this case. /// /// The raw pointer must point to a block of memory allocated by `alloc` /// @@ -1531,6 +1538,7 @@ impl Arc { /// even if the returned `Arc` is never accessed. /// /// [into_raw]: Arc::into_raw + /// [unsized coercion]: https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions /// /// # Examples /// @@ -1553,6 +1561,23 @@ impl Arc { /// /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! /// ``` + /// + /// Convert a slice back into its original array: + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let x: Arc<[u32]> = Arc::new_in([1, 2, 3], System); + /// let x_ptr: *const [u32] = Arc::into_raw(x); + /// + /// unsafe { + /// let x: Arc<[u32; 3]> = Arc::from_raw_in(x_ptr.cast::<[u32; 3]>(), System); + /// assert_eq!(&*x, &[1, 2, 3]); + /// } + /// ``` #[inline] #[unstable(feature = "allocator_api", issue = "32838")] pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self { From bdbbf04a03311a79a193196f7ac64e5fd164af44 Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Sun, 28 Jan 2024 17:33:17 +0100 Subject: [PATCH 6/6] Fix doctest --- library/alloc/src/rc.rs | 5 +++-- library/alloc/src/sync.rs | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index ebd816fba813b..ca4ddaa92a54f 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1387,6 +1387,7 @@ impl Rc { /// even if the returned `Rc` is never accessed. /// /// [into_raw]: Rc::into_raw + /// [transmute]: core::mem::transmute /// [unsized coercion]: https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions /// /// # Examples @@ -1419,11 +1420,11 @@ impl Rc { /// use std::rc::Rc; /// use std::alloc::System; /// - /// let x: Rc<[u32]> = Rc::new_in([1, 2, 3], System); + /// let x: Rc<[u32], _> = Rc::new_in([1, 2, 3], System); /// let x_ptr: *const [u32] = Rc::into_raw(x); /// /// unsafe { - /// let x: Rc<[u32; 3]> = Rc::from_raw_in(x_ptr.cast::<[u32; 3]>(), System); + /// let x: Rc<[u32; 3], _> = Rc::from_raw_in(x_ptr.cast::<[u32; 3]>(), System); /// assert_eq!(&*x, &[1, 2, 3]); /// } /// ``` diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 96f8f57f9e09a..9bf4881869edd 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1538,6 +1538,7 @@ impl Arc { /// even if the returned `Arc` is never accessed. /// /// [into_raw]: Arc::into_raw + /// [transmute]: core::mem::transmute /// [unsized coercion]: https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions /// /// # Examples @@ -1570,11 +1571,11 @@ impl Arc { /// use std::sync::Arc; /// use std::alloc::System; /// - /// let x: Arc<[u32]> = Arc::new_in([1, 2, 3], System); + /// let x: Arc<[u32], _> = Arc::new_in([1, 2, 3], System); /// let x_ptr: *const [u32] = Arc::into_raw(x); /// /// unsafe { - /// let x: Arc<[u32; 3]> = Arc::from_raw_in(x_ptr.cast::<[u32; 3]>(), System); + /// let x: Arc<[u32; 3], _> = Arc::from_raw_in(x_ptr.cast::<[u32; 3]>(), System); /// assert_eq!(&*x, &[1, 2, 3]); /// } /// ```