Rollup merge of #127275 - RalfJung:offset-from-isize-min, r=Amanieu · model-checking/verify-rust-std@5569ece (original) (raw)

`@@ -390,37 +390,26 @@ impl<T: ?Sized> *const T {

`

390

390

`if self.is_null() { None } else { Some(unsafe { &*(self as *const MaybeUninit) }) }

`

391

391

`}

`

392

392

``

393

``

`-

/// Calculates the offset from a pointer.

`

``

393

`+

/// Adds an offset to a pointer.

`

394

394

`///

`

395

395

`` /// count is in units of T; e.g., a count of 3 represents a pointer

``

396

396

`` /// offset of 3 * size_of::<T>() bytes.

``

397

397

`///

`

398

398

`/// # Safety

`

399

399

`///

`

400

``

`-

/// If any of the following conditions are violated, the result is Undefined

`

401

``

`-

/// Behavior:

`

``

400

`+

/// If any of the following conditions are violated, the result is Undefined Behavior:

`

402

401

`///

`

403

``

`-

/// * If the computed offset, in bytes, is non-zero, then both the starting and resulting

`

404

``

`-

/// pointer must be either in bounds or at the end of the same [allocated object].

`

405

``

`-

/// (If it is zero, then the function is always well-defined.)

`

``

402

`` +

/// * The computed offset, count * size_of::<T>() bytes, must not overflow isize.

``

406

403

`///

`

407

``

`` -

/// * The computed offset, in bytes, cannot overflow an isize.

``

``

404

`` +

/// * If the computed offset is non-zero, then self must be derived from a pointer to some

``

``

405

`` +

/// [allocated object], and the entire memory range between self and the result must be in

``

``

406

`+

/// bounds of that allocated object. In particular, this range must not "wrap around" the edge

`

``

407

`+

/// of the address space.

`

408

408

`///

`

409

``

`-

/// * The offset being in bounds cannot rely on "wrapping around" the address

`

410

``

`-

/// space. That is, the infinite-precision sum, in bytes must fit in a usize.

`

411

``

`-

///

`

412

``

`-

/// The compiler and standard library generally tries to ensure allocations

`

413

``

`` -

/// never reach a size where an offset is a concern. For instance, Vec

``

414

``

`` -

/// and Box ensure they never allocate more than isize::MAX bytes, so

``

415

``

`` -

/// vec.as_ptr().add(vec.len()) is always safe.

``

416

``

`-

///

`

417

``

`-

/// Most platforms fundamentally can't even construct such an allocation.

`

418

``

`-

/// For instance, no known 64-bit platform can ever serve a request

`

419

``

`-

/// for 263 bytes due to page-table limitations or splitting the address space.

`

420

``

`-

/// However, some 32-bit and 16-bit platforms may successfully serve a request for

`

421

``

`` -

/// more than isize::MAX bytes with things like Physical Address

``

422

``

`-

/// Extension. As such, memory acquired directly from allocators or memory

`

423

``

`-

/// mapped files may be too large to handle with this function.

`

``

409

`` +

/// Allocated objects can never be larger than isize::MAX bytes, so if the computed offset

``

``

410

`+

/// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.

`

``

411

`` +

/// This implies, for instance, that vec.as_ptr().add(vec.len()) (for vec: Vec<T>) is always

``

``

412

`+

/// safe.

`

424

413

`///

`

425

414

`` /// Consider using [wrapping_offset] instead if these constraints are

``

426

415

`/// difficult to satisfy. The only advantage of this method is that it

`

`@@ -611,8 +600,7 @@ impl<T: ?Sized> *const T {

`

611

600

`///

`

612

601

`/// # Safety

`

613

602

`///

`

614

``

`-

/// If any of the following conditions are violated, the result is Undefined

`

615

``

`-

/// Behavior:

`

``

603

`+

/// If any of the following conditions are violated, the result is Undefined Behavior:

`

616

604

`///

`

617

605

`` /// * self and origin must either

``

618

606

`///

`

`@@ -623,26 +611,10 @@ impl<T: ?Sized> *const T {

`

623

611

`/// * The distance between the pointers, in bytes, must be an exact multiple

`

624

612

`` /// of the size of T.

``

625

613

`///

`

626

``

`` -

/// * The distance between the pointers, in bytes, cannot overflow an isize.

``

627

``

`-

///

`

628

``

`-

/// * The distance being in bounds cannot rely on "wrapping around" the address space.

`

629

``

`-

///

`

630

``

`` -

/// Rust types are never larger than isize::MAX and Rust allocations never wrap around the

``

631

``

`` -

/// address space, so two pointers within some value of any Rust type T will always satisfy

``

632

``

`-

/// the last two conditions. The standard library also generally ensures that allocations

`

633

``

`` -

/// never reach a size where an offset is a concern. For instance, Vec and Box ensure they

``

634

``

`` -

/// never allocate more than isize::MAX bytes, so ptr_into_vec.offset_from(vec.as_ptr())

``

635

``

`-

/// always satisfies the last two conditions.

`

636

``

`-

///

`

637

``

`-

/// Most platforms fundamentally can't even construct such a large allocation.

`

638

``

`-

/// For instance, no known 64-bit platform can ever serve a request

`

639

``

`-

/// for 263 bytes due to page-table limitations or splitting the address space.

`

640

``

`-

/// However, some 32-bit and 16-bit platforms may successfully serve a request for

`

641

``

`` -

/// more than isize::MAX bytes with things like Physical Address

``

642

``

`-

/// Extension. As such, memory acquired directly from allocators or memory

`

643

``

`-

/// mapped files may be too large to handle with this function.

`

644

``

`` -

/// (Note that [offset] and [add] also have a similar limitation and hence cannot be used on

``

645

``

`-

/// such large allocations either.)

`

``

614

`+

/// As a consequence, the absolute distance between the pointers, in bytes, computed on

`

``

615

`` +

/// mathematical integers (without "wrapping around"), cannot overflow an isize. This is

``

``

616

`+

/// implied by the in-bounds requirement, and the fact that no allocated object can be larger

`

``

617

`` +

/// than isize::MAX bytes.

``

646

618

`///

`

647

619

`/// The requirement for pointers to be derived from the same allocated object is primarily

`

648

620

`` /// needed for const-compatibility: the distance between pointers into different allocated

``

`@@ -879,37 +851,26 @@ impl<T: ?Sized> *const T {

`

879

851

`}

`

880

852

`}

`

881

853

``

882

``

`` -

/// Calculates the offset from a pointer (convenience for .offset(count as isize)).

``

``

854

`` +

/// Adds an offset to a pointer (convenience for .offset(count as isize)).

``

883

855

`///

`

884

856

`` /// count is in units of T; e.g., a count of 3 represents a pointer

``

885

857

`` /// offset of 3 * size_of::<T>() bytes.

``

886

858

`///

`

887

859

`/// # Safety

`

888

860

`///

`

889

``

`-

/// If any of the following conditions are violated, the result is Undefined

`

890

``

`-

/// Behavior:

`

``

861

`+

/// If any of the following conditions are violated, the result is Undefined Behavior:

`

891

862

`///

`

892

``

`-

/// * If the computed offset, in bytes, is non-zero, then both the starting and resulting

`

893

``

`-

/// pointer must be either in bounds or at the end of the same [allocated object].

`

894

``

`-

/// (If it is zero, then the function is always well-defined.)

`

``

863

`` +

/// * The computed offset, count * size_of::<T>() bytes, must not overflow isize.

``

895

864

`///

`

896

``

`` -

/// * The computed offset, in bytes, cannot overflow an isize.

``

``

865

`` +

/// * If the computed offset is non-zero, then self must be derived from a pointer to some

``

``

866

`` +

/// [allocated object], and the entire memory range between self and the result must be in

``

``

867

`+

/// bounds of that allocated object. In particular, this range must not "wrap around" the edge

`

``

868

`+

/// of the address space.

`

897

869

`///

`

898

``

`-

/// * The offset being in bounds cannot rely on "wrapping around" the address

`

899

``

`` -

/// space. That is, the infinite-precision sum must fit in a usize.

``

900

``

`-

///

`

901

``

`-

/// The compiler and standard library generally tries to ensure allocations

`

902

``

`` -

/// never reach a size where an offset is a concern. For instance, Vec

``

903

``

`` -

/// and Box ensure they never allocate more than isize::MAX bytes, so

``

904

``

`` -

/// vec.as_ptr().add(vec.len()) is always safe.

``

905

``

`-

///

`

906

``

`-

/// Most platforms fundamentally can't even construct such an allocation.

`

907

``

`-

/// For instance, no known 64-bit platform can ever serve a request

`

908

``

`-

/// for 263 bytes due to page-table limitations or splitting the address space.

`

909

``

`-

/// However, some 32-bit and 16-bit platforms may successfully serve a request for

`

910

``

`` -

/// more than isize::MAX bytes with things like Physical Address

``

911

``

`-

/// Extension. As such, memory acquired directly from allocators or memory

`

912

``

`-

/// mapped files may be too large to handle with this function.

`

``

870

`` +

/// Allocated objects can never be larger than isize::MAX bytes, so if the computed offset

``

``

871

`+

/// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.

`

``

872

`` +

/// This implies, for instance, that vec.as_ptr().add(vec.len()) (for vec: Vec<T>) is always

``

``

873

`+

/// safe.

`

913

874

`///

`

914

875

`` /// Consider using [wrapping_add] instead if these constraints are

``

915

876

`/// difficult to satisfy. The only advantage of this method is that it

`

`@@ -963,38 +924,27 @@ impl<T: ?Sized> *const T {

`

963

924

`unsafe { self.cast::().add(count).with_metadata_of(self) }

`

964

925

`}

`

965

926

``

966

``

`-

/// Calculates the offset from a pointer (convenience for

`

``

927

`+

/// Subtracts an offset from a pointer (convenience for

`

967

928

`` /// .offset((count as isize).wrapping_neg())).

``

968

929

`///

`

969

930

`` /// count is in units of T; e.g., a count of 3 represents a pointer

``

970

931

`` /// offset of 3 * size_of::<T>() bytes.

``

971

932

`///

`

972

933

`/// # Safety

`

973

934

`///

`

974

``

`-

/// If any of the following conditions are violated, the result is Undefined

`

975

``

`-

/// Behavior:

`

976

``

`-

///

`

977

``

`-

/// * If the computed offset, in bytes, is non-zero, then both the starting and resulting

`

978

``

`-

/// pointer must be either in bounds or at the end of the same [allocated object].

`

979

``

`-

/// (If it is zero, then the function is always well-defined.)

`

980

``

`-

///

`

981

``

`` -

/// * The computed offset cannot exceed isize::MAX bytes.

``

``

935

`+

/// If any of the following conditions are violated, the result is Undefined Behavior:

`

982

936

`///

`

983

``

`-

/// * The offset being in bounds cannot rely on "wrapping around" the address

`

984

``

`-

/// space. That is, the infinite-precision sum must fit in a usize.

`

``

937

`` +

/// * The computed offset, count * size_of::<T>() bytes, must not overflow isize.

``

985

938

`///

`

986

``

`-

/// The compiler and standard library generally tries to ensure allocations

`

987

``

`` -

/// never reach a size where an offset is a concern. For instance, Vec

``

988

``

`` -

/// and Box ensure they never allocate more than isize::MAX bytes, so

``

989

``

`` -

/// vec.as_ptr().add(vec.len()).sub(vec.len()) is always safe.

``

``

939

`` +

/// * If the computed offset is non-zero, then self must be derived from a pointer to some

``

``

940

`` +

/// [allocated object], and the entire memory range between self and the result must be in

``

``

941

`+

/// bounds of that allocated object. In particular, this range must not "wrap around" the edge

`

``

942

`+

/// of the address space.

`

990

943

`///

`

991

``

`-

/// Most platforms fundamentally can't even construct such an allocation.

`

992

``

`-

/// For instance, no known 64-bit platform can ever serve a request

`

993

``

`-

/// for 263 bytes due to page-table limitations or splitting the address space.

`

994

``

`-

/// However, some 32-bit and 16-bit platforms may successfully serve a request for

`

995

``

`` -

/// more than isize::MAX bytes with things like Physical Address

``

996

``

`-

/// Extension. As such, memory acquired directly from allocators or memory

`

997

``

`-

/// mapped files may be too large to handle with this function.

`

``

944

`` +

/// Allocated objects can never be larger than isize::MAX bytes, so if the computed offset

``

``

945

`+

/// stays in bounds of the allocated object, it is guaranteed to satisfy the first requirement.

`

``

946

`` +

/// This implies, for instance, that vec.as_ptr().add(vec.len()) (for vec: Vec<T>) is always

``

``

947

`+

/// safe.

`

998

948

`///

`

999

949

`` /// Consider using [wrapping_sub] instead if these constraints are

``

1000

950

`/// difficult to satisfy. The only advantage of this method is that it

`