Skip to content

Commit e9615f2

Browse files
authored
Rollup merge of rust-lang#63297 - RalfJung:ptr_offset, r=dtolnay
Improve pointer offset method docs Cc @rkruppe @gnzlbg
2 parents 0b4823d + 0dc9e2a commit e9615f2

File tree

1 file changed

+128
-34
lines changed

1 file changed

+128
-34
lines changed

src/libcore/ptr/mod.rs

+128-34
Original file line numberDiff line numberDiff line change
@@ -1120,7 +1120,8 @@ impl<T: ?Sized> *const T {
11201120
/// Behavior:
11211121
///
11221122
/// * Both the starting and resulting pointer must be either in bounds or one
1123-
/// byte past the end of the same allocated object.
1123+
/// byte past the end of the same allocated object. Note that in Rust,
1124+
/// every (stack-allocated) variable is considered a separate allocated object.
11241125
///
11251126
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
11261127
///
@@ -1140,10 +1141,12 @@ impl<T: ?Sized> *const T {
11401141
/// Extension. As such, memory acquired directly from allocators or memory
11411142
/// mapped files *may* be too large to handle with this function.
11421143
///
1143-
/// Consider using `wrapping_offset` instead if these constraints are
1144+
/// Consider using [`wrapping_offset`] instead if these constraints are
11441145
/// difficult to satisfy. The only advantage of this method is that it
11451146
/// enables more aggressive compiler optimizations.
11461147
///
1148+
/// [`wrapping_offset`]: #method.wrapping_offset
1149+
///
11471150
/// # Examples
11481151
///
11491152
/// Basic usage:
@@ -1172,15 +1175,26 @@ impl<T: ?Sized> *const T {
11721175
///
11731176
/// The resulting pointer does not need to be in bounds, but it is
11741177
/// potentially hazardous to dereference (which requires `unsafe`).
1175-
/// In particular, the resulting pointer may *not* be used to access a
1176-
/// different allocated object than the one `self` points to. In other
1177-
/// words, `x.wrapping_offset(y.wrapping_offset_from(x))` is
1178+
///
1179+
/// In particular, the resulting pointer remains attached to the same allocated
1180+
/// object that `self` points to. It may *not* be used to access a
1181+
/// different allocated object. Note that in Rust,
1182+
/// every (stack-allocated) variable is considered a separate allocated object.
1183+
///
1184+
/// In other words, `x.wrapping_offset(y.wrapping_offset_from(x))` is
11781185
/// *not* the same as `y`, and dereferencing it is undefined behavior
11791186
/// unless `x` and `y` point into the same allocated object.
11801187
///
1181-
/// Always use `.offset(count)` instead when possible, because `offset`
1182-
/// allows the compiler to optimize better. If you need to cross object
1183-
/// boundaries, cast the pointer to an integer and do the arithmetic there.
1188+
/// Compared to [`offset`], this method basically delays the requirement of staying
1189+
/// within the same allocated object: [`offset`] is immediate Undefined Behavior when
1190+
/// crossing object boundaries; `wrapping_offset` produces a pointer but still leads
1191+
/// to Undefined Behavior if that pointer is dereferenced. [`offset`] can be optimized
1192+
/// better and is thus preferrable in performance-sensitive code.
1193+
///
1194+
/// If you need to cross object boundaries, cast the pointer to an integer and
1195+
/// do the arithmetic there.
1196+
///
1197+
/// [`offset`]: #method.offset
11841198
///
11851199
/// # Examples
11861200
///
@@ -1223,7 +1237,8 @@ impl<T: ?Sized> *const T {
12231237
/// Behavior:
12241238
///
12251239
/// * Both the starting and other pointer must be either in bounds or one
1226-
/// byte past the end of the same allocated object.
1240+
/// byte past the end of the same allocated object. Note that in Rust,
1241+
/// every (stack-allocated) variable is considered a separate allocated object.
12271242
///
12281243
/// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
12291244
///
@@ -1338,7 +1353,8 @@ impl<T: ?Sized> *const T {
13381353
/// Behavior:
13391354
///
13401355
/// * Both the starting and resulting pointer must be either in bounds or one
1341-
/// byte past the end of the same allocated object.
1356+
/// byte past the end of the same allocated object. Note that in Rust,
1357+
/// every (stack-allocated) variable is considered a separate allocated object.
13421358
///
13431359
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
13441360
///
@@ -1358,10 +1374,12 @@ impl<T: ?Sized> *const T {
13581374
/// Extension. As such, memory acquired directly from allocators or memory
13591375
/// mapped files *may* be too large to handle with this function.
13601376
///
1361-
/// Consider using `wrapping_offset` instead if these constraints are
1377+
/// Consider using [`wrapping_add`] instead if these constraints are
13621378
/// difficult to satisfy. The only advantage of this method is that it
13631379
/// enables more aggressive compiler optimizations.
13641380
///
1381+
/// [`wrapping_add`]: #method.wrapping_add
1382+
///
13651383
/// # Examples
13661384
///
13671385
/// Basic usage:
@@ -1395,7 +1413,8 @@ impl<T: ?Sized> *const T {
13951413
/// Behavior:
13961414
///
13971415
/// * Both the starting and resulting pointer must be either in bounds or one
1398-
/// byte past the end of the same allocated object.
1416+
/// byte past the end of the same allocated object. Note that in Rust,
1417+
/// every (stack-allocated) variable is considered a separate allocated object.
13991418
///
14001419
/// * The computed offset cannot exceed `isize::MAX` **bytes**.
14011420
///
@@ -1415,10 +1434,12 @@ impl<T: ?Sized> *const T {
14151434
/// Extension. As such, memory acquired directly from allocators or memory
14161435
/// mapped files *may* be too large to handle with this function.
14171436
///
1418-
/// Consider using `wrapping_offset` instead if these constraints are
1437+
/// Consider using [`wrapping_sub`] instead if these constraints are
14191438
/// difficult to satisfy. The only advantage of this method is that it
14201439
/// enables more aggressive compiler optimizations.
14211440
///
1441+
/// [`wrapping_sub`]: #method.wrapping_sub
1442+
///
14221443
/// # Examples
14231444
///
14241445
/// Basic usage:
@@ -1451,8 +1472,21 @@ impl<T: ?Sized> *const T {
14511472
/// The resulting pointer does not need to be in bounds, but it is
14521473
/// potentially hazardous to dereference (which requires `unsafe`).
14531474
///
1454-
/// Always use `.add(count)` instead when possible, because `add`
1455-
/// allows the compiler to optimize better.
1475+
/// In particular, the resulting pointer remains attached to the same allocated
1476+
/// object that `self` points to. It may *not* be used to access a
1477+
/// different allocated object. Note that in Rust,
1478+
/// every (stack-allocated) variable is considered a separate allocated object.
1479+
///
1480+
/// Compared to [`add`], this method basically delays the requirement of staying
1481+
/// within the same allocated object: [`add`] is immediate Undefined Behavior when
1482+
/// crossing object boundaries; `wrapping_add` produces a pointer but still leads
1483+
/// to Undefined Behavior if that pointer is dereferenced. [`add`] can be optimized
1484+
/// better and is thus preferrable in performance-sensitive code.
1485+
///
1486+
/// If you need to cross object boundaries, cast the pointer to an integer and
1487+
/// do the arithmetic there.
1488+
///
1489+
/// [`add`]: #method.add
14561490
///
14571491
/// # Examples
14581492
///
@@ -1492,8 +1526,21 @@ impl<T: ?Sized> *const T {
14921526
/// The resulting pointer does not need to be in bounds, but it is
14931527
/// potentially hazardous to dereference (which requires `unsafe`).
14941528
///
1495-
/// Always use `.sub(count)` instead when possible, because `sub`
1496-
/// allows the compiler to optimize better.
1529+
/// In particular, the resulting pointer remains attached to the same allocated
1530+
/// object that `self` points to. It may *not* be used to access a
1531+
/// different allocated object. Note that in Rust,
1532+
/// every (stack-allocated) variable is considered a separate allocated object.
1533+
///
1534+
/// Compared to [`sub`], this method basically delays the requirement of staying
1535+
/// within the same allocated object: [`sub`] is immediate Undefined Behavior when
1536+
/// crossing object boundaries; `wrapping_sub` produces a pointer but still leads
1537+
/// to Undefined Behavior if that pointer is dereferenced. [`sub`] can be optimized
1538+
/// better and is thus preferrable in performance-sensitive code.
1539+
///
1540+
/// If you need to cross object boundaries, cast the pointer to an integer and
1541+
/// do the arithmetic there.
1542+
///
1543+
/// [`sub`]: #method.sub
14971544
///
14981545
/// # Examples
14991546
///
@@ -1757,7 +1804,8 @@ impl<T: ?Sized> *mut T {
17571804
/// Behavior:
17581805
///
17591806
/// * Both the starting and resulting pointer must be either in bounds or one
1760-
/// byte past the end of the same allocated object.
1807+
/// byte past the end of the same allocated object. Note that in Rust,
1808+
/// every (stack-allocated) variable is considered a separate allocated object.
17611809
///
17621810
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
17631811
///
@@ -1777,10 +1825,12 @@ impl<T: ?Sized> *mut T {
17771825
/// Extension. As such, memory acquired directly from allocators or memory
17781826
/// mapped files *may* be too large to handle with this function.
17791827
///
1780-
/// Consider using `wrapping_offset` instead if these constraints are
1828+
/// Consider using [`wrapping_offset`] instead if these constraints are
17811829
/// difficult to satisfy. The only advantage of this method is that it
17821830
/// enables more aggressive compiler optimizations.
17831831
///
1832+
/// [`wrapping_offset`]: #method.wrapping_offset
1833+
///
17841834
/// # Examples
17851835
///
17861836
/// Basic usage:
@@ -1808,15 +1858,26 @@ impl<T: ?Sized> *mut T {
18081858
///
18091859
/// The resulting pointer does not need to be in bounds, but it is
18101860
/// potentially hazardous to dereference (which requires `unsafe`).
1811-
/// In particular, the resulting pointer may *not* be used to access a
1812-
/// different allocated object than the one `self` points to. In other
1813-
/// words, `x.wrapping_offset(y.wrapping_offset_from(x))` is
1861+
///
1862+
/// In particular, the resulting pointer remains attached to the same allocated
1863+
/// object that `self` points to. It may *not* be used to access a
1864+
/// different allocated object. Note that in Rust,
1865+
/// every (stack-allocated) variable is considered a separate allocated object.
1866+
///
1867+
/// In other words, `x.wrapping_offset(y.wrapping_offset_from(x))` is
18141868
/// *not* the same as `y`, and dereferencing it is undefined behavior
18151869
/// unless `x` and `y` point into the same allocated object.
18161870
///
1817-
/// Always use `.offset(count)` instead when possible, because `offset`
1818-
/// allows the compiler to optimize better. If you need to cross object
1819-
/// boundaries, cast the pointer to an integer and do the arithmetic there.
1871+
/// Compared to [`offset`], this method basically delays the requirement of staying
1872+
/// within the same allocated object: [`offset`] is immediate Undefined Behavior when
1873+
/// crossing object boundaries; `wrapping_offset` produces a pointer but still leads
1874+
/// to Undefined Behavior if that pointer is dereferenced. [`offset`] can be optimized
1875+
/// better and is thus preferrable in performance-sensitive code.
1876+
///
1877+
/// If you need to cross object boundaries, cast the pointer to an integer and
1878+
/// do the arithmetic there.
1879+
///
1880+
/// [`offset`]: #method.offset
18201881
///
18211882
/// # Examples
18221883
///
@@ -1903,7 +1964,8 @@ impl<T: ?Sized> *mut T {
19031964
/// Behavior:
19041965
///
19051966
/// * Both the starting and other pointer must be either in bounds or one
1906-
/// byte past the end of the same allocated object.
1967+
/// byte past the end of the same allocated object. Note that in Rust,
1968+
/// every (stack-allocated) variable is considered a separate allocated object.
19071969
///
19081970
/// * The distance between the pointers, **in bytes**, cannot overflow an `isize`.
19091971
///
@@ -2007,7 +2069,8 @@ impl<T: ?Sized> *mut T {
20072069
/// Behavior:
20082070
///
20092071
/// * Both the starting and resulting pointer must be either in bounds or one
2010-
/// byte past the end of the same allocated object.
2072+
/// byte past the end of the same allocated object. Note that in Rust,
2073+
/// every (stack-allocated) variable is considered a separate allocated object.
20112074
///
20122075
/// * The computed offset, **in bytes**, cannot overflow an `isize`.
20132076
///
@@ -2027,10 +2090,12 @@ impl<T: ?Sized> *mut T {
20272090
/// Extension. As such, memory acquired directly from allocators or memory
20282091
/// mapped files *may* be too large to handle with this function.
20292092
///
2030-
/// Consider using `wrapping_offset` instead if these constraints are
2093+
/// Consider using [`wrapping_add`] instead if these constraints are
20312094
/// difficult to satisfy. The only advantage of this method is that it
20322095
/// enables more aggressive compiler optimizations.
20332096
///
2097+
/// [`wrapping_add`]: #method.wrapping_add
2098+
///
20342099
/// # Examples
20352100
///
20362101
/// Basic usage:
@@ -2064,7 +2129,8 @@ impl<T: ?Sized> *mut T {
20642129
/// Behavior:
20652130
///
20662131
/// * Both the starting and resulting pointer must be either in bounds or one
2067-
/// byte past the end of the same allocated object.
2132+
/// byte past the end of the same allocated object. Note that in Rust,
2133+
/// every (stack-allocated) variable is considered a separate allocated object.
20682134
///
20692135
/// * The computed offset cannot exceed `isize::MAX` **bytes**.
20702136
///
@@ -2084,10 +2150,12 @@ impl<T: ?Sized> *mut T {
20842150
/// Extension. As such, memory acquired directly from allocators or memory
20852151
/// mapped files *may* be too large to handle with this function.
20862152
///
2087-
/// Consider using `wrapping_offset` instead if these constraints are
2153+
/// Consider using [`wrapping_sub`] instead if these constraints are
20882154
/// difficult to satisfy. The only advantage of this method is that it
20892155
/// enables more aggressive compiler optimizations.
20902156
///
2157+
/// [`wrapping_sub`]: #method.wrapping_sub
2158+
///
20912159
/// # Examples
20922160
///
20932161
/// Basic usage:
@@ -2120,8 +2188,21 @@ impl<T: ?Sized> *mut T {
21202188
/// The resulting pointer does not need to be in bounds, but it is
21212189
/// potentially hazardous to dereference (which requires `unsafe`).
21222190
///
2123-
/// Always use `.add(count)` instead when possible, because `add`
2124-
/// allows the compiler to optimize better.
2191+
/// In particular, the resulting pointer remains attached to the same allocated
2192+
/// object that `self` points to. It may *not* be used to access a
2193+
/// different allocated object. Note that in Rust,
2194+
/// every (stack-allocated) variable is considered a separate allocated object.
2195+
///
2196+
/// Compared to [`add`], this method basically delays the requirement of staying
2197+
/// within the same allocated object: [`add`] is immediate Undefined Behavior when
2198+
/// crossing object boundaries; `wrapping_add` produces a pointer but still leads
2199+
/// to Undefined Behavior if that pointer is dereferenced. [`add`] can be optimized
2200+
/// better and is thus preferrable in performance-sensitive code.
2201+
///
2202+
/// If you need to cross object boundaries, cast the pointer to an integer and
2203+
/// do the arithmetic there.
2204+
///
2205+
/// [`add`]: #method.add
21252206
///
21262207
/// # Examples
21272208
///
@@ -2161,8 +2242,21 @@ impl<T: ?Sized> *mut T {
21612242
/// The resulting pointer does not need to be in bounds, but it is
21622243
/// potentially hazardous to dereference (which requires `unsafe`).
21632244
///
2164-
/// Always use `.sub(count)` instead when possible, because `sub`
2165-
/// allows the compiler to optimize better.
2245+
/// In particular, the resulting pointer remains attached to the same allocated
2246+
/// object that `self` points to. It may *not* be used to access a
2247+
/// different allocated object. Note that in Rust,
2248+
/// every (stack-allocated) variable is considered a separate allocated object.
2249+
///
2250+
/// Compared to [`sub`], this method basically delays the requirement of staying
2251+
/// within the same allocated object: [`sub`] is immediate Undefined Behavior when
2252+
/// crossing object boundaries; `wrapping_sub` produces a pointer but still leads
2253+
/// to Undefined Behavior if that pointer is dereferenced. [`sub`] can be optimized
2254+
/// better and is thus preferrable in performance-sensitive code.
2255+
///
2256+
/// If you need to cross object boundaries, cast the pointer to an integer and
2257+
/// do the arithmetic there.
2258+
///
2259+
/// [`sub`]: #method.sub
21662260
///
21672261
/// # Examples
21682262
///

0 commit comments

Comments
 (0)