219 lines
5.0 KiB
Rust
219 lines
5.0 KiB
Rust
// run-pass
|
|
// check raw fat pointer ops in mir
|
|
// FIXME: please improve this when we get monomorphization support
|
|
|
|
#![feature(raw_ref_op)]
|
|
#![allow(ambiguous_wide_pointer_comparisons)]
|
|
|
|
use std::mem;
|
|
|
|
#[derive(Debug, PartialEq, Eq)]
|
|
struct ComparisonResults {
|
|
lt: bool,
|
|
le: bool,
|
|
gt: bool,
|
|
ge: bool,
|
|
eq: bool,
|
|
ne: bool
|
|
}
|
|
|
|
const LT: ComparisonResults = ComparisonResults {
|
|
lt: true,
|
|
le: true,
|
|
gt: false,
|
|
ge: false,
|
|
eq: false,
|
|
ne: true
|
|
};
|
|
|
|
const EQ: ComparisonResults = ComparisonResults {
|
|
lt: false,
|
|
le: true,
|
|
gt: false,
|
|
ge: true,
|
|
eq: true,
|
|
ne: false
|
|
};
|
|
|
|
const GT: ComparisonResults = ComparisonResults {
|
|
lt: false,
|
|
le: false,
|
|
gt: true,
|
|
ge: true,
|
|
eq: false,
|
|
ne: true
|
|
};
|
|
|
|
fn compare_su8(a: *const S<[u8]>, b: *const S<[u8]>) -> ComparisonResults {
|
|
ComparisonResults {
|
|
lt: a < b,
|
|
le: a <= b,
|
|
gt: a > b,
|
|
ge: a >= b,
|
|
eq: a == b,
|
|
ne: a != b
|
|
}
|
|
}
|
|
|
|
fn compare_au8(a: *const [u8], b: *const [u8]) -> ComparisonResults {
|
|
ComparisonResults {
|
|
lt: a < b,
|
|
le: a <= b,
|
|
gt: a > b,
|
|
ge: a >= b,
|
|
eq: a == b,
|
|
ne: a != b
|
|
}
|
|
}
|
|
|
|
fn compare_foo<'a>(a: *const (dyn Foo+'a), b: *const (dyn Foo+'a)) -> ComparisonResults {
|
|
ComparisonResults {
|
|
lt: a < b,
|
|
le: a <= b,
|
|
gt: a > b,
|
|
ge: a >= b,
|
|
eq: a == b,
|
|
ne: a != b
|
|
}
|
|
}
|
|
|
|
fn simple_eq<'a>(a: *const (dyn Foo+'a), b: *const (dyn Foo+'a)) -> bool {
|
|
let result = a == b;
|
|
result
|
|
}
|
|
|
|
fn assert_inorder<T: Copy>(a: &[T],
|
|
compare: fn(T, T) -> ComparisonResults) {
|
|
for i in 0..a.len() {
|
|
for j in 0..a.len() {
|
|
let cres = compare(a[i], a[j]);
|
|
if i < j {
|
|
assert_eq!(cres, LT);
|
|
} else if i == j {
|
|
assert_eq!(cres, EQ);
|
|
} else {
|
|
assert_eq!(cres, GT);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
trait Foo { fn foo(&self) -> usize; }
|
|
impl<T> Foo for T {
|
|
fn foo(&self) -> usize {
|
|
mem::size_of::<T>()
|
|
}
|
|
}
|
|
|
|
#[allow(dead_code)]
|
|
struct S<T:?Sized>(u32, T);
|
|
|
|
fn main_ref() {
|
|
let array = [0,1,2,3,4];
|
|
let array2 = [5,6,7,8,9];
|
|
|
|
// fat ptr comparison: addr then extra
|
|
|
|
// check ordering for arrays
|
|
let mut ptrs: Vec<*const [u8]> = vec![
|
|
&array[0..0], &array[0..1], &array, &array[1..]
|
|
];
|
|
|
|
let array_addr = &array as *const [u8] as *const u8 as usize;
|
|
let array2_addr = &array2 as *const [u8] as *const u8 as usize;
|
|
if array2_addr < array_addr {
|
|
ptrs.insert(0, &array2);
|
|
} else {
|
|
ptrs.push(&array2);
|
|
}
|
|
assert_inorder(&ptrs, compare_au8);
|
|
|
|
let u8_ = (0u8, 1u8);
|
|
let u32_ = (4u32, 5u32);
|
|
|
|
// check ordering for ptrs
|
|
let buf: &mut [*const dyn Foo] = &mut [
|
|
&u8_, &u8_.0,
|
|
&u32_, &u32_.0,
|
|
];
|
|
buf.sort_by(|u,v| {
|
|
let u : [*const (); 2] = unsafe { mem::transmute(*u) };
|
|
let v : [*const (); 2] = unsafe { mem::transmute(*v) };
|
|
u.cmp(&v)
|
|
});
|
|
assert_inorder(buf, compare_foo);
|
|
|
|
// check ordering for structs containing arrays
|
|
let ss: (S<[u8; 2]>,
|
|
S<[u8; 3]>,
|
|
S<[u8; 2]>) = (
|
|
S(7, [8, 9]),
|
|
S(10, [11, 12, 13]),
|
|
S(4, [5, 6])
|
|
);
|
|
assert_inorder(&[
|
|
&ss.0 as *const S<[u8]>,
|
|
&ss.1 as *const S<[u8]>,
|
|
&ss.2 as *const S<[u8]>
|
|
], compare_su8);
|
|
|
|
assert!(simple_eq(&0u8 as *const _, &0u8 as *const _));
|
|
assert!(!simple_eq(&0u8 as *const _, &1u8 as *const _));
|
|
}
|
|
|
|
// similar to above, but using &raw
|
|
fn main_raw() {
|
|
let array = [0,1,2,3,4];
|
|
let array2 = [5,6,7,8,9];
|
|
|
|
// fat ptr comparison: addr then extra
|
|
|
|
// check ordering for arrays
|
|
let mut ptrs: Vec<*const [u8]> = vec![
|
|
&raw const array[0..0], &raw const array[0..1], &raw const array, &raw const array[1..]
|
|
];
|
|
|
|
let array_addr = &raw const array as *const u8 as usize;
|
|
let array2_addr = &raw const array2 as *const u8 as usize;
|
|
if array2_addr < array_addr {
|
|
ptrs.insert(0, &raw const array2);
|
|
} else {
|
|
ptrs.push(&raw const array2);
|
|
}
|
|
assert_inorder(&ptrs, compare_au8);
|
|
|
|
let u8_ = (0u8, 1u8);
|
|
let u32_ = (4u32, 5u32);
|
|
|
|
// check ordering for ptrs
|
|
let buf: &mut [*const dyn Foo] = &mut [
|
|
&raw const u8_, &raw const u8_.0,
|
|
&raw const u32_, &raw const u32_.0,
|
|
];
|
|
buf.sort_by(|u,v| {
|
|
let u : [*const (); 2] = unsafe { mem::transmute(*u) };
|
|
let v : [*const (); 2] = unsafe { mem::transmute(*v) };
|
|
u.cmp(&v)
|
|
});
|
|
assert_inorder(buf, compare_foo);
|
|
|
|
// check ordering for structs containing arrays
|
|
let ss: (S<[u8; 2]>,
|
|
S<[u8; 3]>,
|
|
S<[u8; 2]>) = (
|
|
S(7, [8, 9]),
|
|
S(10, [11, 12, 13]),
|
|
S(4, [5, 6])
|
|
);
|
|
assert_inorder(&[
|
|
&raw const ss.0 as *const S<[u8]>,
|
|
&raw const ss.1 as *const S<[u8]>,
|
|
&raw const ss.2 as *const S<[u8]>
|
|
], compare_su8);
|
|
}
|
|
|
|
fn main() {
|
|
main_ref();
|
|
main_raw();
|
|
}
|