Skip to content

Commit ae3e67b

Browse files
committed
Auto merge of #390 - RalfJung:strict-provenance, r=Amanieu
use strict provenance APIs on nightly This makes hashbrown compatible with strict provenance, which helps Miri in ensuring pointers are used correctly. Fixes #384
2 parents a2de204 + dd6aceb commit ae3e67b

File tree

4 files changed

+26
-5
lines changed

4 files changed

+26
-5
lines changed

ci/miri.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ rustup toolchain install nightly --component miri
99
rustup override set nightly
1010
cargo miri setup
1111

12-
MIRIFLAGS='-Zmiri-retag-fields' cargo miri test
12+
MIRIFLAGS='-Zmiri-strict-provenance' cargo miri test --features nightly

src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@
2222
slice_ptr_get,
2323
nonnull_slice_from_raw_parts,
2424
maybe_uninit_array_assume_init,
25-
build_hasher_simple_hash_one
25+
build_hasher_simple_hash_one,
26+
strict_provenance
2627
)
2728
)]
2829
#![allow(
@@ -37,6 +38,7 @@
3738
)]
3839
#![warn(missing_docs)]
3940
#![warn(rust_2018_idioms)]
41+
#![cfg_attr(feature = "nightly", warn(fuzzy_provenance_casts))]
4042

4143
#[cfg(test)]
4244
#[macro_use]

src/raw/mod.rs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,16 @@ fn unlikely(b: bool) -> bool {
6969
b
7070
}
7171

72+
// Use strict provenance functions if available.
73+
#[cfg(feature = "nightly")]
74+
use core::ptr::invalid_mut;
75+
// Implement it with a cast otherwise.
76+
#[cfg(not(feature = "nightly"))]
77+
#[inline(always)]
78+
fn invalid_mut<T>(addr: usize) -> *mut T {
79+
addr as *mut T
80+
}
81+
7282
#[inline]
7383
unsafe fn offset_from<T>(to: *const T, from: *const T) -> usize {
7484
to.offset_from(from) as usize
@@ -371,7 +381,7 @@ impl<T> Bucket<T> {
371381
// won't overflow because index must be less than length (bucket_mask)
372382
// and bucket_mask is guaranteed to be less than `isize::MAX`
373383
// (see TableLayout::calculate_layout_for method)
374-
(index + 1) as *mut T
384+
invalid_mut(index + 1)
375385
} else {
376386
base.as_ptr().sub(index)
377387
};
@@ -507,7 +517,8 @@ impl<T> Bucket<T> {
507517
pub fn as_ptr(&self) -> *mut T {
508518
if Self::IS_ZERO_SIZED_TYPE {
509519
// Just return an arbitrary ZST pointer which is properly aligned
510-
mem::align_of::<T>() as *mut T
520+
// invalid pointer is good enough for ZST
521+
invalid_mut(mem::align_of::<T>())
511522
} else {
512523
unsafe { self.ptr.as_ptr().sub(1) }
513524
}
@@ -553,7 +564,8 @@ impl<T> Bucket<T> {
553564
#[inline]
554565
unsafe fn next_n(&self, offset: usize) -> Self {
555566
let ptr = if Self::IS_ZERO_SIZED_TYPE {
556-
(self.ptr.as_ptr() as usize + offset) as *mut T
567+
// invalid pointer is good enough for ZST
568+
invalid_mut(self.ptr.as_ptr() as usize + offset)
557569
} else {
558570
self.ptr.as_ptr().sub(offset)
559571
};

src/set.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2907,4 +2907,11 @@ mod test_set {
29072907
set.insert(i);
29082908
}
29092909
}
2910+
2911+
#[test]
2912+
fn collect() {
2913+
// At the time of writing, this hits the ZST case in from_base_index
2914+
// (and without the `map`, it does not).
2915+
let mut _set: HashSet<_> = (0..3).map(|_| ()).collect();
2916+
}
29102917
}

0 commit comments

Comments
 (0)