X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;ds=sidebyside;f=compiler%2Frustc_mir%2Fsrc%2Finterpret%2Fcast.rs;h=cee4c2e30aa0973c019918601828caeed5a8f025;hb=63ed62531324cd4660deb7faff58e6c17b93b487;hp=514c1aa9646a063c28e50ac54ca11a1a8d755d01;hpb=7069a8c2b78c5d23205de1cabb4c2a65229dbd8f;p=rust.git diff --git a/compiler/rustc_mir/src/interpret/cast.rs b/compiler/rustc_mir/src/interpret/cast.rs index 514c1aa9646..cee4c2e30aa 100644 --- a/compiler/rustc_mir/src/interpret/cast.rs +++ b/compiler/rustc_mir/src/interpret/cast.rs @@ -269,12 +269,34 @@ fn unsize_into_ptr( 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