Skip to content

ptr::offset should explicitly clarify 0-sized offset semantics #65108

Closed

Description

@Gankra

https://doc.rust-lang.org/std/primitive.pointer.html#method.offset

I can't remember the past arguments we definitely had about this, but it would be nice to explicitly call out the answer in the docs.

As a relevant example, Vec::into_iter currently unconditionally computes the "end" pointer of the array by offsetting by len (as long as size_of T > 0). This means that we offset a dangling pointer by 0 when iterating an empty Vec. This is obviously useful to support and annoying to have to guard against, so I would hope that's well-defined.

https://doc.rust-lang.org/src/alloc/vec.rs.html#1860

fn into_iter(mut self) -> IntoIter<T> {
        unsafe {
            let begin = self.as_mut_ptr();
            let end = if mem::size_of::<T>() == 0 {
                arith_offset(begin as *const i8, self.len() as isize) as *const T
            } else {
                // SAFE when `begin` dangles and `len == 0`???
                begin.add(self.len()) as *const T
            };
            let cap = self.buf.capacity();
            mem::forget(self);
            IntoIter {
                buf: NonNull::new_unchecked(begin),
                phantom: PhantomData,
                cap,
                ptr: begin,
                end,
            }
        }
    }

Activity

  1. Gankra commented on Oct 4, 2019

    @Gankra
    ContributorAuthor
  2. Gankra commented on Oct 4, 2019

    @Gankra
    ContributorAuthor

    (For anyone driving by, the ZST branch is an irrelevant distraction. We guarantee ZST ops do nothing, and this code is specially making the offset non-zero so it can use the pointer difference as a counter.)

  3. added
    C-enhancementCategory: An issue proposing an enhancement or a PR with one.
    A-docsArea: Documentation for any part of the project, including the compiler, standard library, and tools
    T-langRelevant to the language team
    T-libs-api[DEPRECATED; DO NOT USE]
    on Oct 4, 2019
  4. RalfJung commented on Oct 9, 2019

    @RalfJung
    Member

    The problem is that we don't really know what LLVM's rules are for getelementptr inbounds with a 0 offset. Also see #54857 of which this seems to be a duplicate, the corresponding UCG issue rust-lang/unsafe-code-guidelines#93, and this thread (spread across 3 months) on the LLVM list:
    https://lists.llvm.org/pipermail/llvm-dev/2019-February/130452.html, https://lists.llvm.org/pipermail/llvm-dev/2019-March/130831.html, https://lists.llvm.org/pipermail/llvm-dev/2019-April/131693.html.

    What Miri currently implements is the most restrictive version that allows current code to work: if you cast an int to a ptr, you may offset that by 0 and it's okay unless that int is 0 (NULL ptrs are special). If you have a "real" pointer, you may only offset it by 0 if it is inbounds of an allocation. With ptr-int-casts this distinction between "real pointers" and integer pointers gets blurry, however...

  5. added 2 commits that reference this issue on May 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-docsArea: Documentation for any part of the project, including the compiler, standard library, and toolsC-enhancementCategory: An issue proposing an enhancement or a PR with one.T-langRelevant to the language teamT-libs-api[DEPRECATED; DO NOT USE]

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions