Skip to content

Commit 865ab57

Browse files
bors[bot]matklad
andauthored
Merge #191
191: simplify strict-provenance polyfill r=matklad a=matklad bors r+ Co-authored-by: Aleksey Kladov <[email protected]>
2 parents f4645cb + d997723 commit 865ab57

File tree

3 files changed

+26
-30
lines changed

3 files changed

+26
-30
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44

55
-
66

7+
## 1.13.1
8+
9+
- Make implementation compliant with [strict provenance](https://github.com/rust-lang/rust/issues/95228).
10+
- Upgrade `atomic-polyfill` to `1.0`
11+
712
## 1.13.0
813

914
- Add `Lazy::get`, similar to `OnceCell::get`.

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "once_cell"
3-
version = "1.13.0"
3+
version = "1.13.1"
44
authors = ["Aleksey Kladov <[email protected]>"]
55
license = "MIT OR Apache-2.0"
66
edition = "2018"

src/imp_std.rs

+20-29
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
// * no poisoning
44
// * init function can fail
55

6-
// Our polyfills collide with the strict_provenance feature
7-
#![allow(unstable_name_collisions)]
8-
96
use std::{
107
cell::{Cell, UnsafeCell},
118
hint::unreachable_unchecked,
@@ -174,11 +171,11 @@ impl Drop for Guard<'_> {
174171
fn drop(&mut self) {
175172
let queue = self.queue.swap(self.new_queue, Ordering::AcqRel);
176173

177-
let state = queue.addr() & STATE_MASK;
174+
let state = strict::addr(queue) & STATE_MASK;
178175
assert_eq!(state, RUNNING);
179176

180177
unsafe {
181-
let mut waiter = queue.map_addr(|q| q & !STATE_MASK);
178+
let mut waiter = strict::map_addr(queue, |q| q & !STATE_MASK);
182179
while !waiter.is_null() {
183180
let next = (*waiter).next;
184181
let thread = (*waiter).thread.take().unwrap();
@@ -201,13 +198,13 @@ fn initialize_or_wait(queue: &AtomicPtr<Waiter>, mut init: Option<&mut dyn FnMut
201198
let mut curr_queue = queue.load(Ordering::Acquire);
202199

203200
loop {
204-
let curr_state = curr_queue.addr() & STATE_MASK;
201+
let curr_state = strict::addr(curr_queue) & STATE_MASK;
205202
match (curr_state, &mut init) {
206203
(COMPLETE, _) => return,
207204
(INCOMPLETE, Some(init)) => {
208205
let exchange = queue.compare_exchange(
209206
curr_queue,
210-
curr_queue.map_addr(|q| (q & !STATE_MASK) | RUNNING),
207+
strict::map_addr(curr_queue, |q| (q & !STATE_MASK) | RUNNING),
211208
Ordering::Acquire,
212209
Ordering::Acquire,
213210
);
@@ -231,23 +228,23 @@ fn initialize_or_wait(queue: &AtomicPtr<Waiter>, mut init: Option<&mut dyn FnMut
231228
}
232229

233230
fn wait(queue: &AtomicPtr<Waiter>, mut curr_queue: *mut Waiter) {
234-
let curr_state = curr_queue.addr() & STATE_MASK;
231+
let curr_state = strict::addr(curr_queue) & STATE_MASK;
235232
loop {
236233
let node = Waiter {
237234
thread: Cell::new(Some(thread::current())),
238235
signaled: AtomicBool::new(false),
239-
next: curr_queue.map_addr(|q| q & !STATE_MASK),
236+
next: strict::map_addr(curr_queue, |q| q & !STATE_MASK),
240237
};
241238
let me = &node as *const Waiter as *mut Waiter;
242239

243240
let exchange = queue.compare_exchange(
244241
curr_queue,
245-
me.map_addr(|q| q | curr_state),
242+
strict::map_addr(me, |q| q | curr_state),
246243
Ordering::Release,
247244
Ordering::Relaxed,
248245
);
249246
if let Err(new_queue) = exchange {
250-
if new_queue.addr() & STATE_MASK != curr_state {
247+
if strict::addr(new_queue) & STATE_MASK != curr_state {
251248
return;
252249
}
253250
curr_queue = new_queue;
@@ -261,32 +258,26 @@ fn wait(queue: &AtomicPtr<Waiter>, mut curr_queue: *mut Waiter) {
261258
}
262259
}
263260

264-
// This trait is copied directly from the implementation of https://crates.io/crates/sptr
265-
trait Strict {
266-
type Pointee;
267-
fn addr(self) -> usize;
268-
fn with_addr(self, addr: usize) -> Self;
269-
fn map_addr(self, f: impl FnOnce(usize) -> usize) -> Self;
270-
}
271-
272-
impl<T> Strict for *mut T {
273-
type Pointee = T;
274-
261+
// Polyfill of strict provenance from https://crates.io/crates/sptr.
262+
//
263+
// Use free-standing function rather than a trait to keep things simple and
264+
// avoid any potential conflicts with future stabile std API.
265+
mod strict {
275266
#[must_use]
276267
#[inline]
277-
fn addr(self) -> usize
268+
pub(crate) fn addr<T>(ptr: *mut T) -> usize
278269
where
279270
T: Sized,
280271
{
281272
// FIXME(strict_provenance_magic): I am magic and should be a compiler intrinsic.
282273
// SAFETY: Pointer-to-integer transmutes are valid (if you are okay with losing the
283274
// provenance).
284-
unsafe { core::mem::transmute(self) }
275+
unsafe { core::mem::transmute(ptr) }
285276
}
286277

287278
#[must_use]
288279
#[inline]
289-
fn with_addr(self, addr: usize) -> Self
280+
pub(crate) fn with_addr<T>(ptr: *mut T, addr: usize) -> *mut T
290281
where
291282
T: Sized,
292283
{
@@ -295,23 +286,23 @@ impl<T> Strict for *mut T {
295286
// In the mean-time, this operation is defined to be "as if" it was
296287
// a wrapping_offset, so we can emulate it as such. This should properly
297288
// restore pointer provenance even under today's compiler.
298-
let self_addr = self.addr() as isize;
289+
let self_addr = self::addr(ptr) as isize;
299290
let dest_addr = addr as isize;
300291
let offset = dest_addr.wrapping_sub(self_addr);
301292

302293
// This is the canonical desugarring of this operation,
303294
// but `pointer::cast` was only stabilized in 1.38.
304295
// self.cast::<u8>().wrapping_offset(offset).cast::<T>()
305-
(self as *mut u8).wrapping_offset(offset) as *mut T
296+
(ptr as *mut u8).wrapping_offset(offset) as *mut T
306297
}
307298

308299
#[must_use]
309300
#[inline]
310-
fn map_addr(self, f: impl FnOnce(usize) -> usize) -> Self
301+
pub(crate) fn map_addr<T>(ptr: *mut T, f: impl FnOnce(usize) -> usize) -> *mut T
311302
where
312303
T: Sized,
313304
{
314-
self.with_addr(f(self.addr()))
305+
self::with_addr(ptr, f(addr(ptr)))
315306
}
316307
}
317308

0 commit comments

Comments
 (0)