Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update documentation for Arc::from_raw, Arc::increment_strong_count, and Arc::decrement_strong_count to clarify allocator requirement #134496

Merged
merged 2 commits into from
Jan 16, 2025

Conversation

DiuDiu777
Copy link
Contributor

@DiuDiu777 DiuDiu777 commented Dec 19, 2024

Related Issue:

This update addresses parts of the issue raised in #134242, where Arc's documentation lacks Global Allocator safety descriptions for three APIs. And this was confirmed by @workingjubilee :

Wait, nevermind. I apparently forgot the increment_strong_count is implicitly A = Global. Ugh. Another reason these things are hard to track, unfortunately.

PR Description

This PR updates the document for the following APIs:

  • Arc::from_raw
  • Arc::increment_strong_count
  • Arc::decrement_strong_count

These APIs currently lack an important piece of documentation: the raw pointer must point to a block of memory allocated by the global allocator. This crucial detail is specified in the source code but is not reflected in the documentation, which could lead to confusion or incorrect usage by users.

Problem:

The following example demonstrates the potential confusion caused by the lack of documentation:

#![feature(allocator_api)]
use std::alloc::{Allocator,AllocError, Layout};
use std::ptr::NonNull;
use std::sync::Arc;

struct LocalAllocator {
    memory: NonNull<u8>,
    size: usize,
}

impl LocalAllocator {
    fn new(size: usize) -> Self {
        Self {
            memory: unsafe { NonNull::new_unchecked(&mut 0u8 as *mut u8) },
            size,
        }
    }
}

unsafe impl Allocator for LocalAllocator {
    fn allocate(&self, _layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
        Ok(NonNull::slice_from_raw_parts(self.memory, self.size))
    }

    unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {
    }
}

fn main() {
    let allocator = LocalAllocator::new(64);
    let arc = Arc::new_in(5, &allocator); // Here, allocator could be any non-global allocator
    let ptr = Arc::into_raw(arc);

    unsafe {
        Arc::increment_strong_count(ptr);
        let arc = Arc::from_raw(ptr);
        assert_eq!(2, Arc::strong_count(&arc)); // Failed here!
    }
}

@rustbot
Copy link
Collaborator

rustbot commented Dec 19, 2024

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @ibraheemdev (or someone else) some time within the next two weeks.

Please see the contribution instructions for more information. Namely, in order to ensure the minimum review times lag, PR authors and assigned reviewers should ensure that the review label (S-waiting-on-review and S-waiting-on-author) stays updated, invoking these commands when appropriate:

  • @rustbot author: the review is finished, PR author should check the comments and take action accordingly
  • @rustbot review: the author is ready for a review, this PR will be queued again in the reviewer's queue

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-libs Relevant to the library team, which will review and decide on the PR/issue. has-merge-commits PR has merge commits, merge with caution. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Dec 19, 2024
@rustbot

This comment was marked as resolved.

@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rustbot

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@rust-log-analyzer

This comment has been minimized.

@jieyouxu jieyouxu removed has-merge-commits PR has merge commits, merge with caution. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Dec 19, 2024
@rustbot rustbot added has-merge-commits PR has merge commits, merge with caution. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Dec 21, 2024
@rustbot

This comment has been minimized.

@rustbot rustbot removed has-merge-commits PR has merge commits, merge with caution. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Dec 21, 2024
@ibraheemdev
Copy link
Member

I'm not sure I understand your example. Creating an Arc from any pointer other than a pointer returned to into_raw is unsound anyways, so your example is unsound in the first call to from_raw. The issue here would be using Arc::new_in and then using Arc::from_raw instead of from_raw_in, or similar.

The change itself looks good to me, but could we link to the appropriate *_in method as well?

@DiuDiu777
Copy link
Contributor Author

@ibraheemdev
Well, the essence of this example is to highlight that the pointers used by from_raw and increment_strong_count can originate from non-Global allocators (a safety concern omitted in the documentation).

You're absolutely right—from_raw is already unsound in this case. But if the pointer originates from new_in with a non-Global allocator (as shown in my updated example), it results in undefined behavior (UB).

The change itself looks good to me, but could we link to the appropriate *_in method as well?

Regarding this issue, I think it would be helpful to explicitly mention Global in the changed parts. While the *_in methods specify that allocations need to use A, users who don't check the from_raw's source code might not realize that it implicitly uses A=Global.

Thanks for taking the time to review this. I hope this clarifies the issue and provides a reasonable update to the std doc.

bors added a commit to rust-lang-ci/rust that referenced this pull request Jan 2, 2025
Fix doc for missing Box allocator consistency

### Description:
This PR addresses missing document regarding consistency of `Box::from_raw` and `Box::from_raw_in`.

- [from_raw](https://doc.rust-lang.org/nightly/std/boxed/struct.Box.html#method.from_raw): The document now misses the raw pointer passed to `Box::from_raw` must point to a block of memory allocated by the `Global Allocator` (specified in source code).

- [from_raw_in](https://doc.rust-lang.org/nightly/std/boxed/struct.Box.html#method.from_raw_in): The safety conditions don't include the allocator consistency.

Besides, [Boxed Memory Layout](https://doc.rust-lang.org/nightly/std/boxed/index.html#memory-layout) doesn't explicitly cover the allocator consistency issue.

This change builds upon the improvements made in [PR rust-lang#134496](rust-lang#134496).
@ibraheemdev
Copy link
Member

r=me after the one typo.

@ibraheemdev
Copy link
Member

ibraheemdev commented Jan 16, 2025

Thanks! @bors r+

@bors
Copy link
Contributor

bors commented Jan 16, 2025

📌 Commit 48e671e has been approved by ibraheemdev

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 16, 2025
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jan 16, 2025
Update documentation for Arc::from_raw, Arc::increment_strong_count, and Arc::decrement_strong_count to clarify allocator requirement

### Related Issue:
This update addresses parts of the issue raised in [rust-lang#134242](rust-lang#134242), where Arc's documentation lacks `Global Allocator` safety descriptions for three APIs. And this was confirmed by `@workingjubilee` :
> Wait, nevermind. I apparently forgot the `increment_strong_count` is implicitly A = Global. Ugh. Another reason these things are hard to track, unfortunately.

### PR Description
This PR updates the document for the following APIs:
- `Arc::from_raw`
- `Arc::increment_strong_count`
- `Arc::decrement_strong_count`

These APIs currently lack an important piece of documentation: **the raw pointer must point to a block of memory allocated by the global allocator**. This crucial detail is specified in the source code but is not reflected in the documentation, which could lead to confusion or incorrect usage by users.

### Problem:
The following example demonstrates the potential confusion caused by the lack of documentation:

```rust
#![feature(allocator_api)]
use std::alloc::{Allocator,AllocError, Layout};
use std::ptr::NonNull;
use std::sync::Arc;

struct LocalAllocator {
    memory: NonNull<u8>,
    size: usize,
}

impl LocalAllocator {
    fn new(size: usize) -> Self {
        Self {
            memory: unsafe { NonNull::new_unchecked(&mut 0u8 as *mut u8) },
            size,
        }
    }
}

unsafe impl Allocator for LocalAllocator {
    fn allocate(&self, _layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
        Ok(NonNull::slice_from_raw_parts(self.memory, self.size))
    }

    unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {
    }
}

fn main() {
    let allocator = LocalAllocator::new(64);
    let arc = Arc::new_in(5, &allocator); // Here, allocator could be any non-global allocator
    let ptr = Arc::into_raw(arc);

    unsafe {
        Arc::increment_strong_count(ptr);
        let arc = Arc::from_raw(ptr);
        assert_eq!(2, Arc::strong_count(&arc)); // Failed here!
    }
}
```
bors added a commit to rust-lang-ci/rust that referenced this pull request Jan 16, 2025
…iaskrgr

Rollup of 7 pull requests

Successful merges:

 - rust-lang#133720 ([cfg_match] Adjust syntax)
 - rust-lang#134496 (Update documentation for Arc::from_raw, Arc::increment_strong_count, and Arc::decrement_strong_count to clarify allocator requirement)
 - rust-lang#134754 (Implement `use` associated items of traits)
 - rust-lang#135249 (Fix overflows in the implementation of `overflowing_literals` lint's help)
 - rust-lang#135251 (Only treat plain literal patterns as short)
 - rust-lang#135556 (Clarify note in `std::sync::LazyLock` example)
 - rust-lang#135560 (Update `compiler-builtins` to 0.1.144)

r? `@ghost`
`@rustbot` modify labels: rollup
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jan 16, 2025
Update documentation for Arc::from_raw, Arc::increment_strong_count, and Arc::decrement_strong_count to clarify allocator requirement

### Related Issue:
This update addresses parts of the issue raised in [rust-lang#134242](rust-lang#134242), where Arc's documentation lacks `Global Allocator` safety descriptions for three APIs. And this was confirmed by ``@workingjubilee`` :
> Wait, nevermind. I apparently forgot the `increment_strong_count` is implicitly A = Global. Ugh. Another reason these things are hard to track, unfortunately.

### PR Description
This PR updates the document for the following APIs:
- `Arc::from_raw`
- `Arc::increment_strong_count`
- `Arc::decrement_strong_count`

These APIs currently lack an important piece of documentation: **the raw pointer must point to a block of memory allocated by the global allocator**. This crucial detail is specified in the source code but is not reflected in the documentation, which could lead to confusion or incorrect usage by users.

### Problem:
The following example demonstrates the potential confusion caused by the lack of documentation:

```rust
#![feature(allocator_api)]
use std::alloc::{Allocator,AllocError, Layout};
use std::ptr::NonNull;
use std::sync::Arc;

struct LocalAllocator {
    memory: NonNull<u8>,
    size: usize,
}

impl LocalAllocator {
    fn new(size: usize) -> Self {
        Self {
            memory: unsafe { NonNull::new_unchecked(&mut 0u8 as *mut u8) },
            size,
        }
    }
}

unsafe impl Allocator for LocalAllocator {
    fn allocate(&self, _layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
        Ok(NonNull::slice_from_raw_parts(self.memory, self.size))
    }

    unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {
    }
}

fn main() {
    let allocator = LocalAllocator::new(64);
    let arc = Arc::new_in(5, &allocator); // Here, allocator could be any non-global allocator
    let ptr = Arc::into_raw(arc);

    unsafe {
        Arc::increment_strong_count(ptr);
        let arc = Arc::from_raw(ptr);
        assert_eq!(2, Arc::strong_count(&arc)); // Failed here!
    }
}
```
bors added a commit to rust-lang-ci/rust that referenced this pull request Jan 16, 2025
…iaskrgr

Rollup of 6 pull requests

Successful merges:

 - rust-lang#133720 ([cfg_match] Adjust syntax)
 - rust-lang#134496 (Update documentation for Arc::from_raw, Arc::increment_strong_count, and Arc::decrement_strong_count to clarify allocator requirement)
 - rust-lang#135249 (Fix overflows in the implementation of `overflowing_literals` lint's help)
 - rust-lang#135251 (Only treat plain literal patterns as short)
 - rust-lang#135556 (Clarify note in `std::sync::LazyLock` example)
 - rust-lang#135560 (Update `compiler-builtins` to 0.1.144)

r? `@ghost`
`@rustbot` modify labels: rollup
bors added a commit to rust-lang-ci/rust that referenced this pull request Jan 16, 2025
…iaskrgr

Rollup of 5 pull requests

Successful merges:

 - rust-lang#133720 ([cfg_match] Adjust syntax)
 - rust-lang#134496 (Update documentation for Arc::from_raw, Arc::increment_strong_count, and Arc::decrement_strong_count to clarify allocator requirement)
 - rust-lang#135249 (Fix overflows in the implementation of `overflowing_literals` lint's help)
 - rust-lang#135251 (Only treat plain literal patterns as short)
 - rust-lang#135556 (Clarify note in `std::sync::LazyLock` example)

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 87b3671 into rust-lang:master Jan 16, 2025
6 checks passed
@rustbot rustbot added this to the 1.86.0 milestone Jan 16, 2025
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Jan 16, 2025
Rollup merge of rust-lang#134496 - DiuDiu777:fix-doc, r=ibraheemdev

Update documentation for Arc::from_raw, Arc::increment_strong_count, and Arc::decrement_strong_count to clarify allocator requirement

### Related Issue:
This update addresses parts of the issue raised in [rust-lang#134242](rust-lang#134242), where Arc's documentation lacks `Global Allocator` safety descriptions for three APIs. And this was confirmed by ```@workingjubilee``` :
> Wait, nevermind. I apparently forgot the `increment_strong_count` is implicitly A = Global. Ugh. Another reason these things are hard to track, unfortunately.

### PR Description
This PR updates the document for the following APIs:
- `Arc::from_raw`
- `Arc::increment_strong_count`
- `Arc::decrement_strong_count`

These APIs currently lack an important piece of documentation: **the raw pointer must point to a block of memory allocated by the global allocator**. This crucial detail is specified in the source code but is not reflected in the documentation, which could lead to confusion or incorrect usage by users.

### Problem:
The following example demonstrates the potential confusion caused by the lack of documentation:

```rust
#![feature(allocator_api)]
use std::alloc::{Allocator,AllocError, Layout};
use std::ptr::NonNull;
use std::sync::Arc;

struct LocalAllocator {
    memory: NonNull<u8>,
    size: usize,
}

impl LocalAllocator {
    fn new(size: usize) -> Self {
        Self {
            memory: unsafe { NonNull::new_unchecked(&mut 0u8 as *mut u8) },
            size,
        }
    }
}

unsafe impl Allocator for LocalAllocator {
    fn allocate(&self, _layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
        Ok(NonNull::slice_from_raw_parts(self.memory, self.size))
    }

    unsafe fn deallocate(&self, _ptr: NonNull<u8>, _layout: Layout) {
    }
}

fn main() {
    let allocator = LocalAllocator::new(64);
    let arc = Arc::new_in(5, &allocator); // Here, allocator could be any non-global allocator
    let ptr = Arc::into_raw(arc);

    unsafe {
        Arc::increment_strong_count(ptr);
        let arc = Arc::from_raw(ptr);
        assert_eq!(2, Arc::strong_count(&arc)); // Failed here!
    }
}
```
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jan 28, 2025
Add missing allocator safety in alloc crate

### PR Description
In the previous PR [rust-lang#135009](rust-lang#135009), PR [rust-lang#134496](rust-lang#134496), some incomplete API documentation issues have been fixed.

Based on these changes,  other inconsistencies related to the allocator have also been identified, including:

- `Box::from_non_null`
- `Box::from_non_null_in`
- `Weak::from_raw`
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Jan 28, 2025
Add missing allocator safety in alloc crate

### PR Description
In the previous PR [rust-lang#135009](rust-lang#135009), PR [rust-lang#134496](rust-lang#134496), some incomplete API documentation issues have been fixed.

Based on these changes,  other inconsistencies related to the allocator have also been identified, including:

- `Box::from_non_null`
- `Box::from_non_null_in`
- `Weak::from_raw`
rust-timer added a commit to rust-lang-ci/rust that referenced this pull request Jan 28, 2025
Rollup merge of rust-lang#135805 - DiuDiu777:master, r=Noratrieb

Add missing allocator safety in alloc crate

### PR Description
In the previous PR [rust-lang#135009](rust-lang#135009), PR [rust-lang#134496](rust-lang#134496), some incomplete API documentation issues have been fixed.

Based on these changes,  other inconsistencies related to the allocator have also been identified, including:

- `Box::from_non_null`
- `Box::from_non_null_in`
- `Weak::from_raw`
github-actions bot pushed a commit to rust-lang/miri that referenced this pull request Jan 29, 2025
Add missing allocator safety in alloc crate

### PR Description
In the previous PR [#135009](rust-lang/rust#135009), PR [#134496](rust-lang/rust#134496), some incomplete API documentation issues have been fixed.

Based on these changes,  other inconsistencies related to the allocator have also been identified, including:

- `Box::from_non_null`
- `Box::from_non_null_in`
- `Weak::from_raw`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants