Skip to content

Commit d69cbfd

Browse files
committed
Clumsy workaround for rustc complaint
rust-lang/rust#93367
1 parent aed9e2e commit d69cbfd

File tree

4 files changed

+33
-22
lines changed

4 files changed

+33
-22
lines changed

Diff for: src/capi.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ use crate::Image;
1111
use crate::rows::RowCallback;
1212
use crate::seacow::RowBitmapMut;
1313
use crate::seacow::SeaCow;
14+
use crate::seacow::Pointer;
1415
use std::mem::MaybeUninit;
1516

1617
pub const LIQ_VERSION: u32 = 40000;
@@ -20,18 +21,18 @@ pub fn liq_get_palette_impl(r: &mut QuantizationResult) -> &Palette {
2021
}
2122

2223
pub unsafe fn liq_image_create_rgba_rows_impl<'rows>(attr: &Attributes, rows: &'rows [*const RGBA], width: u32, height: u32, gamma: f64) -> Option<crate::image::Image<'rows>> {
23-
let rows = SeaCow::borrowed(rows);
24+
let rows = SeaCow::borrowed(std::mem::transmute::<&'rows [*const RGBA], &'rows [Pointer<RGBA>]>(rows));
2425
let rows_slice = rows.as_slice();
25-
if rows_slice.iter().any(|r| r.is_null()) {
26+
if rows_slice.iter().any(|r| r.0.is_null()) {
2627
return None;
2728
}
2829
crate::image::Image::new_internal(attr, crate::rows::PixelsSource::Pixels { rows, pixels: None }, width, height, gamma).ok()
2930
}
3031

3132
pub unsafe fn liq_image_create_rgba_bitmap_impl<'rows>(attr: &Attributes, rows: Box<[*const RGBA]>, width: u32, height: u32, gamma: f64) -> Option<crate::image::Image<'rows>> {
32-
let rows = SeaCow::boxed(rows);
33+
let rows = SeaCow::boxed(std::mem::transmute::<Box<[*const RGBA]>, Box<[Pointer<RGBA>]>>(rows));
3334
let rows_slice = rows.as_slice();
34-
if rows_slice.iter().any(|r| r.is_null()) {
35+
if rows_slice.iter().any(|r| r.0.is_null()) {
3536
return None;
3637
}
3738
crate::image::Image::new_internal(attr, crate::rows::PixelsSource::Pixels { rows, pixels: None }, width, height, gamma).ok()

Diff for: src/image.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use crate::remap::DitherMapMode;
66
use crate::rows::{DynamicRows, PixelsSource};
77
use crate::seacow::RowBitmap;
88
use crate::seacow::SeaCow;
9+
use crate::seacow::Pointer;
910
use crate::LIQ_HIGH_MEMORY_LIMIT;
1011
use rgb::ComponentMap;
1112
use std::mem::MaybeUninit;
@@ -329,7 +330,7 @@ impl<'pixels> Image<'pixels> {
329330
return Err(BufferTooSmall);
330331
}
331332

332-
let rows = SeaCow::boxed(slice.chunks(stride).map(|row| row.as_ptr()).take(height).collect());
333+
let rows = SeaCow::boxed(slice.chunks(stride).map(|row| Pointer(row.as_ptr())).take(height).collect());
333334
Image::new_internal(attr, PixelsSource::Pixels { rows, pixels: Some(pixels) }, width as u32, height as u32, gamma)
334335
}
335336
}

Diff for: src/rows.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@ use crate::pal::{f_pixel, gamma_lut, RGBA};
33
use crate::seacow::SeaCow;
44
use crate::LIQ_HIGH_MEMORY_LIMIT;
55
use std::mem::MaybeUninit;
6+
use crate::seacow::Pointer;
67

78
pub(crate) type RowCallback<'a> = dyn Fn(&mut [MaybeUninit<RGBA>], usize) + Send + Sync + 'a;
89

910
pub(crate) enum PixelsSource<'pixels, 'rows> {
1011
/// The `pixels` field is never read, but it is used to store the rows.
1112
#[allow(dead_code)]
12-
Pixels { rows: SeaCow<'rows, *const RGBA>, pixels: Option<SeaCow<'pixels, RGBA>> },
13+
Pixels { rows: SeaCow<'rows, Pointer<RGBA>>, pixels: Option<SeaCow<'pixels, RGBA>> },
1314
Callback(Box<RowCallback<'rows>>),
1415
}
1516

@@ -71,7 +72,7 @@ impl<'pixels,'rows> DynamicRows<'pixels,'rows> {
7172
fn row_rgba<'px>(&'px self, temp_row: &'px mut [MaybeUninit<RGBA>], row: usize) -> &[RGBA] {
7273
match &self.pixels {
7374
PixelsSource::Pixels { rows, .. } => unsafe {
74-
std::slice::from_raw_parts(rows.as_slice()[row], self.width())
75+
std::slice::from_raw_parts(rows.as_slice()[row].0, self.width())
7576
},
7677
PixelsSource::Callback(cb) => {
7778
cb(temp_row, row);
@@ -168,7 +169,7 @@ impl<'pixels,'rows> DynamicRows<'pixels,'rows> {
168169
PixelsSource::Pixels { pixels: Some(pixels), .. } => pixels.make_owned(free_fn),
169170
PixelsSource::Pixels { pixels, rows } => {
170171
// the row with the lowest address is assumed to be at the start of the bitmap
171-
let ptr = rows.as_slice().iter().copied().min().ok_or(Error::Unsupported)?;
172+
let ptr = rows.as_slice().iter().map(|p| p.0).min().ok_or(Error::Unsupported)?;
172173
*pixels = Some(SeaCow::c_owned(ptr as *mut _, len, free_fn));
173174
},
174175
PixelsSource::Callback(_) => return Err(Error::ValueOutOfRange),

Diff for: src/seacow.rs

+22-14
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,20 @@ pub struct SeaCow<'a, T> {
99
unsafe impl<T: Send> Send for SeaCowInner<'_, T> {}
1010
unsafe impl<T: Sync> Sync for SeaCowInner<'_, T> {}
1111

12-
unsafe impl<T: Send> Send for SeaCow<'_, *const T> {}
13-
unsafe impl<T: Sync> Sync for SeaCow<'_, *const T> {}
12+
/// Rust assumes `*const T` is never `Send`/`Sync`, but it can be.
13+
/// This is fudge for https://github.com/rust-lang/rust/issues/93367
14+
#[repr(transparent)]
15+
#[derive(Copy, Clone)]
16+
pub(crate) struct Pointer<T>(pub *const T);
17+
18+
#[derive(Copy, Clone)]
19+
#[repr(transparent)]
20+
pub(crate) struct PointerMut<T>(pub *mut T);
21+
22+
unsafe impl<T: Send + Sync> Send for Pointer<T> {}
23+
unsafe impl<T: Send + Sync> Sync for Pointer<T> {}
24+
unsafe impl<T: Send + Sync> Send for PointerMut<T> {}
25+
unsafe impl<T: Send + Sync> Sync for PointerMut<T> {}
1426

1527
impl<'a, T> SeaCow<'a, T> {
1628
#[inline]
@@ -78,13 +90,13 @@ impl<'a, T> SeaCow<'a, T> {
7890
}
7991

8092
pub(crate) struct RowBitmap<'a, T> {
81-
rows: &'a [*const T],
93+
rows: &'a [Pointer<T>],
8294
width: usize,
8395
}
8496
unsafe impl<T: Send + Sync> Send for RowBitmap<'_, T> {}
8597

8698
pub(crate) struct RowBitmapMut<'a, T> {
87-
rows: MutCow<'a, [*mut T]>,
99+
rows: MutCow<'a, [PointerMut<T>]>,
88100
width: usize,
89101
}
90102
unsafe impl<T: Send + Sync> Send for RowBitmapMut<'_, T> {}
@@ -94,16 +106,16 @@ impl<'a, T> RowBitmapMut<'a, MaybeUninit<T>> {
94106
pub(crate) unsafe fn assume_init<'maybeowned>(&'maybeowned mut self) -> RowBitmap<'maybeowned, T> {
95107
RowBitmap {
96108
width: self.width,
97-
rows: std::mem::transmute::<&'maybeowned [*mut MaybeUninit<T>], &'maybeowned [*const T]>(self.rows.borrow()),
109+
rows: std::mem::transmute::<&'maybeowned [PointerMut<MaybeUninit<T>>], &'maybeowned [Pointer<T>]>(self.rows.borrow()),
98110
}
99111
}
100112
}
101113

102114
impl<'a, T> RowBitmap<'a, T> {
103115
pub fn rows(&self) -> impl Iterator<Item = &[T]> {
104116
let width = self.width;
105-
self.rows.iter().map(move |&row| {
106-
unsafe { std::slice::from_raw_parts(row, width) }
117+
self.rows.iter().map(move |row| {
118+
unsafe { std::slice::from_raw_parts(row.0, width) }
107119
})
108120
}
109121
}
@@ -127,7 +139,7 @@ impl<'a, T: Sync + Send + Copy + 'static> RowBitmapMut<'a, T> {
127139
#[inline]
128140
pub fn new_contiguous(data: &mut [T], width: usize) -> Self {
129141
Self {
130-
rows: MutCow::Owned(data.chunks_exact_mut(width).map(|r| r.as_mut_ptr()).collect()),
142+
rows: MutCow::Owned(data.chunks_exact_mut(width).map(|r| PointerMut(r.as_mut_ptr())).collect()),
131143
width,
132144
}
133145
}
@@ -137,18 +149,14 @@ impl<'a, T: Sync + Send + Copy + 'static> RowBitmapMut<'a, T> {
137149
#[cfg(feature = "_internal_c_ffi")]
138150
pub unsafe fn new(rows: &'a mut [*mut T], width: usize) -> Self {
139151
Self {
140-
rows: MutCow::Borrowed(rows),
152+
rows: MutCow::Borrowed(std::mem::transmute::<&'a mut [*mut T], &'a mut [PointerMut<T>]>(rows)),
141153
width,
142154
}
143155
}
144156

145157
pub fn rows_mut(&mut self) -> impl Iterator<Item = &mut [T]> + Send {
146158
let width = self.width;
147-
// Rust is pessimistic about `*mut` pointers
148-
struct ItIsSync<T>(*mut T);
149-
unsafe impl<T: Send + Sync> Sync for ItIsSync<T> {}
150-
let send_slice = unsafe { std::mem::transmute::<&mut [*mut T], &mut [ItIsSync<T>]>(self.rows.borrow()) };
151-
send_slice.iter().map(move |row| {
159+
self.rows.borrow().iter().map(move |row| {
152160
unsafe { std::slice::from_raw_parts_mut(row.0, width) }
153161
})
154162
}

0 commit comments

Comments
 (0)