Skip to content

Commit 2ce5387

Browse files
committed
Rename load_value_pair to load_scalar_pair and fix dynamic dispatch with arbitrary self types
1 parent 57feadc commit 2ce5387

8 files changed

+135
-30
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Adapted from rustc run-pass test suite
2+
3+
#![feature(no_core, arbitrary_self_types, box_syntax)]
4+
#![feature(rustc_attrs)]
5+
6+
#![feature(start, lang_items)]
7+
#![no_core]
8+
9+
extern crate mini_core;
10+
11+
use mini_core::*;
12+
use mini_core::libc::*;
13+
14+
macro_rules! assert_eq {
15+
($l:expr, $r: expr) => {
16+
if $l != $r {
17+
panic(&(stringify!($l != $r), file!(), line!(), 0));
18+
}
19+
}
20+
}
21+
22+
struct Ptr<T: ?Sized>(Box<T>);
23+
24+
impl<T: ?Sized> Deref for Ptr<T> {
25+
type Target = T;
26+
27+
fn deref(&self) -> &T {
28+
&*self.0
29+
}
30+
}
31+
32+
impl<T: Unsize<U> + ?Sized, U: ?Sized> CoerceUnsized<Ptr<U>> for Ptr<T> {}
33+
impl<T: Unsize<U> + ?Sized, U: ?Sized> DispatchFromDyn<Ptr<U>> for Ptr<T> {}
34+
35+
struct Wrapper<T: ?Sized>(T);
36+
37+
impl<T: ?Sized> Deref for Wrapper<T> {
38+
type Target = T;
39+
40+
fn deref(&self) -> &T {
41+
&self.0
42+
}
43+
}
44+
45+
impl<T: CoerceUnsized<U>, U> CoerceUnsized<Wrapper<U>> for Wrapper<T> {}
46+
impl<T: DispatchFromDyn<U>, U> DispatchFromDyn<Wrapper<U>> for Wrapper<T> {}
47+
48+
49+
trait Trait {
50+
// This method isn't object-safe yet. Unsized by-value `self` is object-safe (but not callable
51+
// without unsized_locals), but wrappers arond `Self` currently are not.
52+
// FIXME (mikeyhew) uncomment this when unsized rvalues object-safety is implemented
53+
// fn wrapper(self: Wrapper<Self>) -> i32;
54+
fn ptr_wrapper(self: Ptr<Wrapper<Self>>) -> i32;
55+
fn wrapper_ptr(self: Wrapper<Ptr<Self>>) -> i32;
56+
fn wrapper_ptr_wrapper(self: Wrapper<Ptr<Wrapper<Self>>>) -> i32;
57+
}
58+
59+
impl Trait for i32 {
60+
fn ptr_wrapper(self: Ptr<Wrapper<Self>>) -> i32 {
61+
**self
62+
}
63+
fn wrapper_ptr(self: Wrapper<Ptr<Self>>) -> i32 {
64+
**self
65+
}
66+
fn wrapper_ptr_wrapper(self: Wrapper<Ptr<Wrapper<Self>>>) -> i32 {
67+
***self
68+
}
69+
}
70+
71+
#[start]
72+
fn main(_: isize, _: *const *const u8) -> isize {
73+
let pw = Ptr(box Wrapper(5)) as Ptr<Wrapper<dyn Trait>>;
74+
assert_eq!(pw.ptr_wrapper(), 5);
75+
76+
let wp = Wrapper(Ptr(box 6)) as Wrapper<Ptr<dyn Trait>>;
77+
assert_eq!(wp.wrapper_ptr(), 6);
78+
79+
let wpw = Wrapper(Ptr(box Wrapper(7))) as Wrapper<Ptr<Wrapper<dyn Trait>>>;
80+
assert_eq!(wpw.wrapper_ptr_wrapper(), 7);
81+
82+
0
83+
}

example/mini_core.rs

+25
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ impl<'a, T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut
2727
impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
2828
// *mut T -> *mut U
2929
impl<T: ?Sized+Unsize<U>, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
30+
impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Box<U>> for Box<T> {}
3031

3132
#[lang = "receiver"]
3233
pub trait Receiver {}
@@ -216,6 +217,15 @@ impl PartialEq for usize {
216217
}
217218
}
218219

220+
impl PartialEq for i32 {
221+
fn eq(&self, other: &i32) -> bool {
222+
(*self) == (*other)
223+
}
224+
fn ne(&self, other: &i32) -> bool {
225+
(*self) != (*other)
226+
}
227+
}
228+
219229
impl PartialEq for isize {
220230
fn eq(&self, other: &isize) -> bool {
221231
(*self) == (*other)
@@ -306,6 +316,13 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
306316
drop_in_place(to_drop);
307317
}
308318

319+
#[lang = "deref"]
320+
pub trait Deref {
321+
type Target: ?Sized;
322+
323+
fn deref(&self) -> &Self::Target;
324+
}
325+
309326
#[lang = "owned_box"]
310327
pub struct Box<T: ?Sized>(*mut T);
311328

@@ -317,6 +334,14 @@ impl<T: ?Sized> Drop for Box<T> {
317334
}
318335
}
319336

337+
impl<T> Deref for Box<T> {
338+
type Target = T;
339+
340+
fn deref(&self) -> &Self::Target {
341+
&**self
342+
}
343+
}
344+
320345
#[lang = "exchange_malloc"]
321346
// Make it available to jited mini_core_hello_world
322347
// FIXME remove next line when jit supports linking rlibs

src/base.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ fn trans_stmt<'a, 'tcx: 'a>(
537537
lval.write_cvalue(fx, operand.unchecked_cast_to(dest_layout));
538538
} else {
539539
// fat-ptr -> thin-ptr
540-
let (ptr, _extra) = operand.load_value_pair(fx);
540+
let (ptr, _extra) = operand.load_scalar_pair(fx);
541541
lval.write_cvalue(fx, CValue::ByVal(ptr, dest_layout))
542542
}
543543
} else if let ty::Adt(adt_def, _substs) = from_ty.sty {
@@ -1101,8 +1101,8 @@ fn trans_ptr_binop<'a, 'tcx: 'a>(
11011101
Offset (_) bug; // Handled above
11021102
}
11031103
} else {
1104-
let (lhs_ptr, lhs_extra) = lhs.load_value_pair(fx);
1105-
let (rhs_ptr, rhs_extra) = rhs.load_value_pair(fx);
1104+
let (lhs_ptr, lhs_extra) = lhs.load_scalar_pair(fx);
1105+
let (rhs_ptr, rhs_extra) = rhs.load_scalar_pair(fx);
11061106
let res = match bin_op {
11071107
BinOp::Eq => {
11081108
let ptr_eq = fx.bcx.ins().icmp(IntCC::Equal, lhs_ptr, rhs_ptr);

src/common.rs

+16-16
Original file line numberDiff line numberDiff line change
@@ -166,33 +166,33 @@ impl<'tcx> CValue<'tcx> {
166166
fx.bcx.ins().load(clif_ty, MemFlags::new(), addr, 0)
167167
}
168168
CValue::ByVal(value, _layout) => value,
169-
CValue::ByValPair(_, _, _layout) => bug!("Please use load_value_pair for ByValPair"),
169+
CValue::ByValPair(_, _, _layout) => bug!("Please use load_scalar_pair for ByValPair"),
170170
}
171171
}
172172

173-
pub fn load_value_pair<'a>(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> (Value, Value)
173+
/// Load a value pair with layout.abi of scalar pair
174+
pub fn load_scalar_pair<'a>(self, fx: &mut FunctionCx<'a, 'tcx, impl Backend>) -> (Value, Value)
174175
where
175176
'tcx: 'a,
176177
{
177178
match self {
178179
CValue::ByRef(addr, layout) => {
179-
assert_eq!(
180-
layout.size.bytes(),
181-
fx.tcx.data_layout.pointer_size.bytes() * 2
180+
let (a, b) = match &layout.abi {
181+
layout::Abi::ScalarPair(a, b) => (a.clone(), b.clone()),
182+
_ => unreachable!(),
183+
};
184+
let clif_ty1 = crate::abi::scalar_to_clif_type(fx.tcx, a.clone());
185+
let clif_ty2 = crate::abi::scalar_to_clif_type(fx.tcx, b);
186+
let val1 = fx.bcx.ins().load(clif_ty1, MemFlags::new(), addr, 0);
187+
let val2 = fx.bcx.ins().load(
188+
clif_ty2,
189+
MemFlags::new(),
190+
addr,
191+
a.value.size(&fx.tcx).bytes() as i32,
182192
);
183-
let val1_offset = layout.fields.offset(0).bytes() as i32;
184-
let val2_offset = layout.fields.offset(1).bytes() as i32;
185-
let val1 = fx
186-
.bcx
187-
.ins()
188-
.load(fx.pointer_type, MemFlags::new(), addr, val1_offset);
189-
let val2 = fx
190-
.bcx
191-
.ins()
192-
.load(fx.pointer_type, MemFlags::new(), addr, val2_offset);
193193
(val1, val2)
194194
}
195-
CValue::ByVal(_, _layout) => bug!("Please use load_value for ByVal"),
195+
CValue::ByVal(_, _layout) => bug!("Please use load_scalar for ByVal"),
196196
CValue::ByValPair(val1, val2, _layout) => (val1, val2),
197197
}
198198
}

src/intrinsics.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>(
156156
size_of_val, <T> (c ptr) {
157157
let layout = fx.layout_of(T);
158158
let size = if layout.is_unsized() {
159-
let (_ptr, info) = ptr.load_value_pair(fx);
159+
let (_ptr, info) = ptr.load_scalar_pair(fx);
160160
let (size, _align) = crate::unsize::size_and_align_of_dst(fx, layout.ty, info);
161161
size
162162
} else {
@@ -175,7 +175,7 @@ pub fn codegen_intrinsic_call<'a, 'tcx: 'a>(
175175
min_align_of_val, <T> (c ptr) {
176176
let layout = fx.layout_of(T);
177177
let align = if layout.is_unsized() {
178-
let (_ptr, info) = ptr.load_value_pair(fx);
178+
let (_ptr, info) = ptr.load_scalar_pair(fx);
179179
let (_size, align) = crate::unsize::size_and_align_of_dst(fx, layout.ty, info);
180180
align
181181
} else {

src/unsize.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ pub fn coerce_unsized_into<'a, 'tcx: 'a>(
9696
{
9797
// fat-ptr to fat-ptr unsize preserves the vtable
9898
// i.e., &'a fmt::Debug+Send => &'a fmt::Debug
99-
src.load_value_pair(fx)
99+
src.load_scalar_pair(fx)
100100
} else {
101101
let base = src.load_scalar(fx);
102102
unsize_thin_ptr(fx, base, src_ty, dst_ty)

src/vtable.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,7 @@ pub fn get_ptr_and_method_ref<'a, 'tcx: 'a>(
5050
arg: CValue<'tcx>,
5151
idx: usize,
5252
) -> (Value, Value) {
53-
let arg = if arg.layout().ty.is_box() {
54-
// Cast `Box<T>` to `*mut T` so `load_value_pair` works
55-
arg.unchecked_cast_to(fx.layout_of(fx.tcx.mk_mut_ptr(arg.layout().ty.boxed_ty())))
56-
} else {
57-
arg
58-
};
59-
60-
let (ptr, vtable) = arg.load_value_pair(fx);
53+
let (ptr, vtable) = arg.load_scalar_pair(fx);
6154
let usize_size = fx.layout_of(fx.tcx.types.usize).size.bytes();
6255
let func_ref = fx.bcx.ins().load(
6356
pointer_ty(fx.tcx),

test.sh

+4
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ echo "[AOT] mini_core_hello_world"
1717
$RUSTC example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin
1818
./target/out/mini_core_hello_world abc bcd
1919

20+
echo "[AOT] arbitrary_self_types_pointers_and_wrappers"
21+
$RUSTC example/arbitrary_self_types_pointers_and_wrappers.rs --crate-name arbitrary_self_types_pointers_and_wrappers --crate-type bin
22+
./target/out/arbitrary_self_types_pointers_and_wrappers
23+
2024
echo "[BUILD] sysroot"
2125
time ./build_sysroot/build_sysroot.sh
2226

0 commit comments

Comments
 (0)