Skip to content

Commit aa95ebc

Browse files
authored
Auto merge of servo#345 - servo:cow-rc-str, r=glandium
cow-rc-str: Use ptr::NonNull. This fixes UB caught by miri.
2 parents 0ebd17b + 6cd4285 commit aa95ebc

File tree

1 file changed

+17
-30
lines changed

1 file changed

+17
-30
lines changed

src/cow_rc_str.rs

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,37 +3,24 @@
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

55
use std::borrow::{Borrow, Cow};
6-
use std::cmp;
7-
use std::fmt;
8-
use std::hash;
9-
use std::marker::PhantomData;
10-
use std::mem;
11-
use std::ops::Deref;
126
use std::rc::Rc;
13-
use std::slice;
14-
use std::str;
7+
use std::{cmp, fmt, hash, marker, mem, ops, slice, str, ptr};
158

169
/// A string that is either shared (heap-allocated and reference-counted) or borrowed.
1710
///
1811
/// Equivalent to `enum { Borrowed(&'a str), Shared(Rc<String>) }`, but stored more compactly.
1912
///
20-
/// FIXME(https://github.com/rust-lang/rfcs/issues/1230): use an actual enum if/when
21-
/// the compiler can do this layout optimization.
13+
/// * If `borrowed_len_or_max == usize::MAX`, then `ptr` represents `NonZero<*const String>`
14+
/// from `Rc::into_raw`.
15+
/// The lifetime parameter `'a` is irrelevant in this case.
16+
///
17+
/// * Otherwise, `ptr` represents the `NonZero<*const u8>` data component of `&'a str`,
18+
/// and `borrowed_len_or_max` its length.
2219
pub struct CowRcStr<'a> {
23-
/// FIXME: https://github.com/rust-lang/rust/issues/27730 use NonZero or Shared.
24-
/// In the meantime we abuse `&'static _` to get the effect of `NonZero<*const _>`.
25-
/// `ptr` doesn’t really have the 'static lifetime!
26-
ptr: &'static (),
27-
28-
/// * If `borrowed_len_or_max == usize::MAX`, then `ptr` represents `NonZero<*const String>`
29-
/// from `Rc::into_raw`.
30-
/// The lifetime parameter `'a` is irrelevant in this case.
31-
///
32-
/// * Otherwise, `ptr` represents the `NonZero<*const u8>` data component of `&'a str`,
33-
/// and `borrowed_len_or_max` its length.
20+
ptr: ptr::NonNull<()>,
3421
borrowed_len_or_max: usize,
3522

36-
phantom: PhantomData<Result<&'a str, Rc<String>>>,
23+
phantom: marker::PhantomData<Result<&'a str, Rc<String>>>,
3724
}
3825

3926
fn _static_assert_same_size<'a>() {
@@ -57,9 +44,9 @@ impl<'a> From<&'a str> for CowRcStr<'a> {
5744
let len = s.len();
5845
assert!(len < usize::MAX);
5946
CowRcStr {
60-
ptr: unsafe { &*(s.as_ptr() as *const ()) },
47+
ptr: unsafe { ptr::NonNull::new_unchecked(s.as_ptr() as *mut ()) },
6148
borrowed_len_or_max: len,
62-
phantom: PhantomData,
49+
phantom: marker::PhantomData,
6350
}
6451
}
6552
}
@@ -74,22 +61,22 @@ impl<'a> From<String> for CowRcStr<'a> {
7461
impl<'a> CowRcStr<'a> {
7562
#[inline]
7663
fn from_rc(s: Rc<String>) -> Self {
77-
let ptr = unsafe { &*(Rc::into_raw(s) as *const ()) };
64+
let ptr = unsafe { ptr::NonNull::new_unchecked(Rc::into_raw(s) as *mut ()) };
7865
CowRcStr {
79-
ptr: ptr,
66+
ptr,
8067
borrowed_len_or_max: usize::MAX,
81-
phantom: PhantomData,
68+
phantom: marker::PhantomData,
8269
}
8370
}
8471

8572
#[inline]
8673
fn unpack(&self) -> Result<&'a str, *const String> {
8774
if self.borrowed_len_or_max == usize::MAX {
88-
Err(self.ptr as *const () as *const String)
75+
Err(self.ptr.as_ptr() as *const String)
8976
} else {
9077
unsafe {
9178
Ok(str::from_utf8_unchecked(slice::from_raw_parts(
92-
self.ptr as *const () as *const u8,
79+
self.ptr.as_ptr() as *const u8,
9380
self.borrowed_len_or_max,
9481
)))
9582
}
@@ -121,7 +108,7 @@ impl<'a> Drop for CowRcStr<'a> {
121108
}
122109
}
123110

124-
impl<'a> Deref for CowRcStr<'a> {
111+
impl<'a> ops::Deref for CowRcStr<'a> {
125112
type Target = str;
126113

127114
#[inline]

0 commit comments

Comments
 (0)