From 778fdf2dfb0e110d2cf955b827c3d9cfe147235b Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 19 Jul 2023 07:32:24 -0700 Subject: [PATCH 1/7] Add note that Vec::as_mut_ptr() does not materialize a reference to the internal buffer --- library/alloc/src/vec/mod.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 598ecf05e8246..565865231e795 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1218,6 +1218,12 @@ impl Vec { /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer /// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`]. /// + /// This method guarantees that when it is called multiple times without + /// the buffer being reallocated in the mean time, the returned pointer will + /// always be exactly the same, even for the purpose of the aliasing model, where + /// pointers may be invalidated even when the actual memory does not move. + /// See the second example below for how this can be used. + /// /// # Examples /// /// ``` @@ -1231,6 +1237,16 @@ impl Vec { /// } /// ``` /// + /// The validity guarantee works out this way: + /// + /// ```rust + /// let mut v = vec![0]; + /// let ptr = v.as_ptr(); + /// let x = ptr.read(); + /// v[0] = 5; + /// // Notably, the write above did *not* invalidate `ptr1`: + /// let x = ptr.read(); + /// ``` /// [`as_mut_ptr`]: Vec::as_mut_ptr #[stable(feature = "vec_as_ptr", since = "1.37.0")] #[inline] @@ -1248,6 +1264,13 @@ impl Vec { /// Modifying the vector may cause its buffer to be reallocated, /// which would also make any pointers to it invalid. /// + /// This method guarantees that when it is called multiple times without + /// the buffer being reallocated in the mean time, the returned pointer will + /// always be exactly the same, even for the purpose of the aliasing model, where + /// pointers may be invalidated even when the actual memory does not move. + /// See the second example below for how this can be used. + /// + /// /// # Examples /// /// ``` @@ -1265,6 +1288,18 @@ impl Vec { /// } /// assert_eq!(&*x, &[0, 1, 2, 3]); /// ``` + /// + /// The validity guarantee works out this way: + /// + /// ```rust + /// let mut v = vec![0]; + /// let ptr1 = v.as_mut_ptr(); + /// ptr1.write(1); + /// let ptr2 = v.as_mut_ptr(); + /// ptr2.write(2); + /// // Notably, the write to `ptr2` did *not* invalidate `ptr1`: + /// ptr1.write(3); + /// ``` #[stable(feature = "vec_as_ptr", since = "1.37.0")] #[inline] pub fn as_mut_ptr(&mut self) -> *mut T { From 3809c091fc25339f606d510b3835182b0cd0dbc7 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 26 Jul 2023 18:41:37 -0700 Subject: [PATCH 2/7] aliasing guarantee --- library/alloc/src/vec/mod.rs | 65 ++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 565865231e795..626e2f5f0fad5 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1218,11 +1218,14 @@ impl Vec { /// is never written to (except inside an `UnsafeCell`) using this pointer or any pointer /// derived from it. If you need to mutate the contents of the slice, use [`as_mut_ptr`]. /// - /// This method guarantees that when it is called multiple times without - /// the buffer being reallocated in the mean time, the returned pointer will - /// always be exactly the same, even for the purpose of the aliasing model, where - /// pointers may be invalidated even when the actual memory does not move. - /// See the second example below for how this can be used. + /// This method guarantees that for the purpose of the aliasing model, this method + /// does not materialize a reference to the underlying slice, and thus the returned pointer + /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`], + /// Note that calling other methods that materialize mutable references to the slice, + /// or references to specific elements you are planning on accessing through this pointer, + /// may still invalidate this pointer. + /// See the second example below for how this guarantee can be used. + /// /// /// # Examples /// @@ -1237,17 +1240,22 @@ impl Vec { /// } /// ``` /// - /// The validity guarantee works out this way: + /// Due to the aliasing guarantee, the following code is legal: /// /// ```rust - /// let mut v = vec![0]; - /// let ptr = v.as_ptr(); - /// let x = ptr.read(); - /// v[0] = 5; - /// // Notably, the write above did *not* invalidate `ptr1`: - /// let x = ptr.read(); + /// unsafe { + /// let mut v = vec![0]; + /// let ptr1 = v.as_ptr(); + /// let _ = ptr1.read(); + /// let ptr2 = v.as_mut_ptr(); + /// ptr2.write(2); + /// // Notably, the write to `ptr2` did *not* invalidate `ptr1`: + /// let _ = ptr1.read(); + /// } /// ``` + /// /// [`as_mut_ptr`]: Vec::as_mut_ptr + /// [`as_ptr`]: Vec::as_ptr #[stable(feature = "vec_as_ptr", since = "1.37.0")] #[inline] pub fn as_ptr(&self) -> *const T { @@ -1264,11 +1272,13 @@ impl Vec { /// Modifying the vector may cause its buffer to be reallocated, /// which would also make any pointers to it invalid. /// - /// This method guarantees that when it is called multiple times without - /// the buffer being reallocated in the mean time, the returned pointer will - /// always be exactly the same, even for the purpose of the aliasing model, where - /// pointers may be invalidated even when the actual memory does not move. - /// See the second example below for how this can be used. + /// This method guarantees that for the purpose of the aliasing model, this method + /// does not materialize a reference to the underlying slice, and thus the returned pointer + /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`], + /// Note that calling other methods that materialize references to the slice, + /// or references to specific elements you are planning on accessing through this pointer, + /// may still invalidate this pointer. + /// See the second example below for how this guarantee can be used. /// /// /// # Examples @@ -1289,17 +1299,22 @@ impl Vec { /// assert_eq!(&*x, &[0, 1, 2, 3]); /// ``` /// - /// The validity guarantee works out this way: + /// Due to the aliasing guarantee, the following code is legal: /// /// ```rust - /// let mut v = vec![0]; - /// let ptr1 = v.as_mut_ptr(); - /// ptr1.write(1); - /// let ptr2 = v.as_mut_ptr(); - /// ptr2.write(2); - /// // Notably, the write to `ptr2` did *not* invalidate `ptr1`: - /// ptr1.write(3); + /// unsafe { + /// let mut v = vec![0]; + /// let ptr1 = v.as_mut_ptr(); + /// ptr1.write(1); + /// let ptr2 = v.as_mut_ptr(); + /// ptr2.write(2); + /// // Notably, the write to `ptr2` did *not* invalidate `ptr1`: + /// ptr1.write(3); + /// } /// ``` + /// + /// [`as_mut_ptr`]: Vec::as_mut_ptr + /// [`as_ptr`]: Vec::as_ptr #[stable(feature = "vec_as_ptr", since = "1.37.0")] #[inline] pub fn as_mut_ptr(&mut self) -> *mut T { From 90642ad6795687c803a61bfdaa87f46e2262cf44 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 15 Aug 2023 15:05:49 +0000 Subject: [PATCH 3/7] Update library/alloc/src/vec/mod.rs Co-authored-by: Ralf Jung --- library/alloc/src/vec/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 626e2f5f0fad5..6a7ec917b2ff2 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1220,7 +1220,7 @@ impl Vec { /// /// This method guarantees that for the purpose of the aliasing model, this method /// does not materialize a reference to the underlying slice, and thus the returned pointer - /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`], + /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`]. /// Note that calling other methods that materialize mutable references to the slice, /// or references to specific elements you are planning on accessing through this pointer, /// may still invalidate this pointer. From 10fc06fb819297373295ea48c1f37692ed33f8e7 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 15 Aug 2023 15:06:06 +0000 Subject: [PATCH 4/7] Update library/alloc/src/vec/mod.rs Co-authored-by: Ralf Jung --- library/alloc/src/vec/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 6a7ec917b2ff2..9654e1d699711 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1274,7 +1274,7 @@ impl Vec { /// /// This method guarantees that for the purpose of the aliasing model, this method /// does not materialize a reference to the underlying slice, and thus the returned pointer - /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`], + /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`]. /// Note that calling other methods that materialize references to the slice, /// or references to specific elements you are planning on accessing through this pointer, /// may still invalidate this pointer. From 5bf1bfd784f3143e383f77d42b5c04752fd473e7 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Tue, 15 Aug 2023 15:00:27 -0700 Subject: [PATCH 5/7] other elements --- library/alloc/src/vec/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 9654e1d699711..6c238fd2d0cf9 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1222,7 +1222,7 @@ impl Vec { /// does not materialize a reference to the underlying slice, and thus the returned pointer /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`]. /// Note that calling other methods that materialize mutable references to the slice, - /// or references to specific elements you are planning on accessing through this pointer, + /// or mutable references to specific elements you are planning on accessing through this pointer, /// may still invalidate this pointer. /// See the second example below for how this guarantee can be used. /// @@ -1244,10 +1244,10 @@ impl Vec { /// /// ```rust /// unsafe { - /// let mut v = vec![0]; + /// let mut v = vec![0, 1, 2]; /// let ptr1 = v.as_ptr(); /// let _ = ptr1.read(); - /// let ptr2 = v.as_mut_ptr(); + /// let ptr2 = v.as_mut_ptr().offset(2); /// ptr2.write(2); /// // Notably, the write to `ptr2` did *not* invalidate `ptr1`: /// let _ = ptr1.read(); From 6c6875d8ecb1df024920ab7a80aa70cf5b385ddc Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 16 Aug 2023 19:50:05 +0000 Subject: [PATCH 6/7] Update library/alloc/src/vec/mod.rs Co-authored-by: Ralf Jung --- library/alloc/src/vec/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 6c238fd2d0cf9..2bf25b3e01cbc 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1249,7 +1249,8 @@ impl Vec { /// let _ = ptr1.read(); /// let ptr2 = v.as_mut_ptr().offset(2); /// ptr2.write(2); - /// // Notably, the write to `ptr2` did *not* invalidate `ptr1`: + /// // Notably, the write to `ptr2` did *not* invalidate `ptr1` + /// // because it mutated a different element: /// let _ = ptr1.read(); /// } /// ``` From 7cea69c9a22fb2adec3ab78be281c8c5561a8b09 Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 16 Aug 2023 20:36:21 +0000 Subject: [PATCH 7/7] Update library/alloc/src/vec/mod.rs Co-authored-by: Ralf Jung --- library/alloc/src/vec/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 2bf25b3e01cbc..5fa184daf9c96 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -1223,7 +1223,7 @@ impl Vec { /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`]. /// Note that calling other methods that materialize mutable references to the slice, /// or mutable references to specific elements you are planning on accessing through this pointer, - /// may still invalidate this pointer. + /// as well as writing to those elements, may still invalidate this pointer. /// See the second example below for how this guarantee can be used. /// ///