Immediate::new_slice(ptr, length.eval_usize(*self.tcx, self.param_env), self);
self.write_immediate(val, dest)
}
- (&ty::Dynamic(..), &ty::Dynamic(..)) => {
- // For now, upcasts are limited to changes in marker
- // traits, and hence never actually require an actual
- // change to the vtable.
+ (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => {
let val = self.read_immediate(src)?;
- self.write_immediate(*val, dest)
+ if data_a.principal_def_id() == data_b.principal_def_id() {
+ return self.write_immediate(*val, dest);
+ }
+ // trait upcasting coercion
+ let principal_a = data_a.principal().expect(
+ "unsize_into_ptr: missing principal trait for trait upcasting coercion",
+ );
+ let principal_b = data_b.principal().expect(
+ "unsize_into_ptr: missing principal trait for trait upcasting coercion",
+ );
+
+ let vptr_entry_idx = self.tcx.vtable_trait_upcasting_coercion_new_vptr_slot((
+ principal_a.with_self_ty(*self.tcx, src_pointee_ty),
+ principal_b.with_self_ty(*self.tcx, src_pointee_ty),
+ ));
+
+ if let Some(entry_idx) = vptr_entry_idx {
+ let entry_idx = u64::try_from(entry_idx).unwrap();
+ let (old_data, old_vptr) = val.to_scalar_pair()?;
+ let old_vptr = self.scalar_to_ptr(old_vptr);
+ let new_vptr = self
+ .read_new_vtable_after_trait_upcasting_from_vtable(old_vptr, entry_idx)?;
+ self.write_immediate(Immediate::new_dyn_trait(old_data, new_vptr, self), dest)
+ } else {
+ self.write_immediate(*val, dest)
+ }
}
(_, &ty::Dynamic(ref data, _)) => {
// Initial cast from sized to dyn trait