Skip to content

Commit 5f7af80

Browse files
Handle dyn* coercions for values that are represented with OperandValue::Ref
1 parent d962ea5 commit 5f7af80

File tree

10 files changed

+256
-14
lines changed

10 files changed

+256
-14
lines changed

compiler/rustc_codegen_ssa/src/base.rs

+4
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,10 @@ pub fn cast_to_dyn_star<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
276276
// FIXME(dyn-star): We can remove this when all supported LLVMs use opaque ptrs only.
277277
let unit_ptr = bx.cx().type_ptr_to(bx.cx().type_struct(&[], false));
278278
let src = match bx.cx().type_kind(bx.cx().backend_type(src_ty_and_layout)) {
279+
// if `is_backend_immediate` is not true, then the value is
280+
// represented by an `OperandValue::Ref`, and it's already
281+
// been read into a usize.
282+
_ if !bx.cx().is_backend_immediate(src_ty_and_layout) => src,
279283
TypeKind::Pointer => bx.pointercast(src, unit_ptr),
280284
TypeKind::Integer => bx.inttoptr(src, unit_ptr),
281285
// FIXME(dyn-star): We probably have to do a bitcast first, then inttoptr.

compiler/rustc_codegen_ssa/src/mir/rvalue.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -270,9 +270,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
270270
}
271271
mir::CastKind::DynStar => {
272272
let (lldata, llextra) = match operand.val {
273-
OperandValue::Ref(_, _, _) => todo!(),
273+
OperandValue::Ref(ptr, None, align) => {
274+
// Read the value as a `usize` -- this should be possible,
275+
// since the value is guaranteed to be a properly aligned
276+
// and sized.
277+
let isize_ptr_ty = bx.cx().type_ptr_to(bx.cx().type_isize());
278+
let ptr = bx.pointercast(ptr, isize_ptr_ty);
279+
let v = bx.load(bx.cx().type_isize(), ptr, align);
280+
(v, None)
281+
}
274282
OperandValue::Immediate(v) => (v, None),
275283
OperandValue::Pair(v, l) => (v, Some(l)),
284+
OperandValue::Ref(a, b, _) =>
285+
bug!("unexpected operand cast to dyn*: lldata={a:?} llextra={b:?}"),
276286
};
277287
let (lldata, llextra) =
278288
base::cast_to_dyn_star(bx, lldata, operand.layout, cast.ty, llextra);

compiler/rustc_const_eval/src/interpret/cast.rs

+8-5
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
123123
DynStar => {
124124
if let ty::Dynamic(data, _, ty::DynStar) = cast_ty.kind() {
125125
// Initial cast from sized to dyn trait
126+
// Copy the data into the first field of the destination.
127+
// (Can be a non-immediate type, so we have to do a proper copy.)
128+
let data_dest = self.place_field(dest, 0)?;
129+
self.copy_op(src, &data_dest, true)?;
130+
131+
// Copy the vtable into the second field of the destination.
126132
let vtable = self.get_vtable_ptr(src.layout.ty, data.principal())?;
127-
let vtable = Scalar::from_maybe_pointer(vtable, self);
128-
let data = self.read_immediate(src)?.to_scalar();
129-
let _assert_pointer_like = data.to_pointer(self)?;
130-
let val = Immediate::ScalarPair(data, vtable);
131-
self.write_immediate(val, dest)?;
133+
let vtable_dest = self.place_field(dest, 1)?;
134+
self.write_pointer(vtable, &vtable_dest)?;
132135
} else {
133136
bug!()
134137
}

compiler/rustc_const_eval/src/interpret/operand.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
404404
Abi::Scalar(abi::Scalar::Initialized { .. })
405405
| Abi::ScalarPair(abi::Scalar::Initialized { .. }, abi::Scalar::Initialized { .. })
406406
) {
407-
span_bug!(self.cur_span(), "primitive read not possible for type: {:?}", op.layout.ty);
407+
span_bug!(self.cur_span(), "primitive read not possible for: {:?}", op.layout);
408408
}
409409
let imm = self.read_immediate_raw(op)?.right().unwrap();
410410
if matches!(*imm, Immediate::Uninit) {

compiler/rustc_middle/src/ty/layout.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -774,12 +774,7 @@ where
774774
TyMaybeWithLayout::Ty(tcx.mk_mut_ptr(tcx.types.unit))
775775
} else if i == 1 {
776776
// FIXME(dyn-star) same FIXME as above applies here too
777-
TyMaybeWithLayout::Ty(
778-
tcx.mk_imm_ref(
779-
tcx.lifetimes.re_static,
780-
tcx.mk_array(tcx.types.usize, 3),
781-
),
782-
)
777+
TyMaybeWithLayout::Ty(tcx.mk_imm_ptr(tcx.mk_array(tcx.types.usize, 3)))
783778
} else {
784779
bug!("no field {i} on dyn*")
785780
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#![feature(dyn_star)]
2+
#![allow(incomplete_features)]
3+
4+
use std::fmt::Debug;
5+
6+
#[derive(Debug)]
7+
#[repr(C)]
8+
pub struct Foo(usize);
9+
10+
fn main() {
11+
let x = Foo(1) as dyn* Debug;
12+
assert_eq!(format!("{x:?}"), "Foo(1)");
13+
}

0 commit comments

Comments
 (0)