diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs index f6b9ddf2eea..cae46ebd2e9 100644 --- a/compiler/rustc_codegen_ssa/src/meth.rs +++ b/compiler/rustc_codegen_ssa/src/meth.rs @@ -86,6 +86,7 @@ fn expect_dyn_trait_in_self<'tcx>(ty: Ty<'tcx>) -> ty::PolyExistentialTraitRef<' /// The `trait_ref` encodes the erased self type. Hence if we are /// making an object `Foo` from a value of type `Foo`, then /// `trait_ref` would map `T: Trait`. +#[instrument(level = "debug", skip(cx))] pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( cx: &Cx, ty: Ty<'tcx>, @@ -93,8 +94,6 @@ pub fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>( ) -> Cx::Value { let tcx = cx.tcx(); - debug!("get_vtable(ty={:?}, trait_ref={:?})", ty, trait_ref); - // Check the cache. if let Some(&val) = cx.vtables().borrow().get(&(ty, trait_ref)) { return val; diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index fb75ecc1735..438bb133fd1 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -16,7 +16,7 @@ use rustc_middle::mir::{self, AssertKind, SwitchTargets}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; -use rustc_middle::ty::{self, Instance, Ty, TypeVisitable, TraitObjectRepresentation}; +use rustc_middle::ty::{self, Instance, TraitObjectRepresentation, Ty, TypeVisitable}; use rustc_span::source_map::Span; use rustc_span::{sym, Symbol}; use rustc_symbol_mangling::typeid::typeid_for_fnabi; @@ -451,7 +451,27 @@ fn codegen_drop_terminator( // (data, vtable) // an equivalent Rust `*mut dyn Trait` // // SO THEN WE CAN USE THE ABOVE CODE. - todo!() + let virtual_drop = Instance { + def: ty::InstanceDef::Virtual(drop_fn.def_id(), 0), + substs: drop_fn.substs, + }; + debug!("ty = {:?}", ty); + debug!("drop_fn = {:?}", drop_fn); + debug!("args = {:?}", args); + let fn_abi = bx.fn_abi_of_instance(virtual_drop, ty::List::empty()); + let data = args[0]; + let data_ty = bx.cx().backend_type(place.layout); + let vtable_ptr = + bx.gep(data_ty, data, &[bx.cx().const_i32(0), bx.cx().const_i32(1)]); + let vtable = bx.load(bx.type_i8p(), vtable_ptr, abi::Align::ONE); + // Truncate vtable off of args list + args = &args[..1]; + debug!("args' = {:?}", args); + ( + meth::VirtualIndex::from_index(ty::COMMON_VTABLE_ENTRIES_DROPINPLACE) + .get_fn(&mut bx, vtable, ty, &fn_abi), + fn_abi, + ) } _ => (bx.get_fn_addr(drop_fn), bx.fn_abi_of_instance(drop_fn, ty::List::empty())), }; diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index d3c6b731de3..d68a89fe793 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -4,6 +4,7 @@ use crate::base; use crate::common::{self, IntPredicate}; +use crate::meth::get_vtable; use crate::traits::*; use crate::MemFlags; @@ -11,6 +12,7 @@ use rustc_middle::mir::Operand; use rustc_middle::ty::cast::{CastTy, IntTy}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; +use rustc_middle::ty::TraitObjectRepresentation; use rustc_middle::ty::{self, adjustment::PointerCast, Instance, Ty, TyCtxt}; use rustc_span::source_map::{Span, DUMMY_SP}; @@ -271,14 +273,19 @@ pub fn codegen_rvalue_operand( bug!("unexpected non-pair operand"); } } - #[allow(unreachable_code, unused)] // FIXME: remove this mir::CastKind::DynStar => { let data = match operand.val { OperandValue::Ref(_, _, _) => todo!(), - OperandValue::Immediate(_) => todo!(), + OperandValue::Immediate(v) => v, OperandValue::Pair(_, _) => todo!(), }; - let vtable = todo!(); + // FIXME: find the real vtable! + let trait_ref = if let ty::Dynamic(data, _, TraitObjectRepresentation::Sized) = cast.ty.kind() { + data.principal() + } else { + bug!("Only valid to do a DynStar cast into a DynStar type") + }; + let vtable = get_vtable(bx.cx(), source.ty(self.mir, bx.tcx()), trait_ref); OperandValue::Pair(data, vtable) } mir::CastKind::Pointer( diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 2e68b96f87b..240bead5494 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2751,6 +2751,7 @@ impl<'tcx> ty::Instance<'tcx> { // for `Instance` (e.g. typeck would use `Ty::fn_sig` instead), // or should go through `FnAbi` instead, to avoid losing any // adjustments `fn_abi_of_instance` might be performing. + #[tracing::instrument(level = "debug", skip(tcx, param_env))] fn fn_sig_for_fn_abi( &self, tcx: TyCtxt<'tcx>, @@ -2897,6 +2898,7 @@ fn fn_sig_for_fn_abi( /// with `-Cpanic=abort` will look like they can't unwind when in fact they /// might (from a foreign exception or similar). #[inline] +#[tracing::instrument(level = "debug", skip(tcx))] pub fn fn_can_unwind<'tcx>(tcx: TyCtxt<'tcx>, fn_def_id: Option, abi: SpecAbi) -> bool { if let Some(did) = fn_def_id { // Special attribute for functions which can't unwind. @@ -3113,6 +3115,7 @@ fn fn_abi_of_fn_ptr( /// NB: that includes virtual calls, which are represented by "direct calls" /// to an `InstanceDef::Virtual` instance (of `::fn`). #[inline] + #[tracing::instrument(level = "debug", skip(self))] fn fn_abi_of_instance( &self, instance: ty::Instance<'tcx>, @@ -3259,6 +3262,10 @@ pub fn adjust_for_rust_scalar<'tcx>( impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // FIXME(eddyb) perhaps group the signature/type-containing (or all of them?) // arguments of this method, into a separate `struct`. + #[tracing::instrument( + level = "debug", + skip(self, caller_location, fn_def_id, force_thin_self_ptr) + )] fn fn_abi_new_uncached( &self, sig: ty::PolyFnSig<'tcx>, @@ -3268,8 +3275,6 @@ fn fn_abi_new_uncached( // FIXME(eddyb) replace this with something typed, like an `enum`. force_thin_self_ptr: bool, ) -> Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, FnAbiError<'tcx>> { - debug!("fn_abi_new_uncached({:?}, {:?})", sig, extra_args); - let sig = self.tcx.normalize_erasing_late_bound_regions(self.param_env, sig); let conv = conv_from_spec_abi(self.tcx(), sig.abi); @@ -3312,6 +3317,8 @@ fn fn_abi_new_uncached( let rust_abi = matches!(sig.abi, RustIntrinsic | PlatformIntrinsic | Rust | RustCall); let arg_of = |ty: Ty<'tcx>, arg_idx: Option| -> Result<_, FnAbiError<'tcx>> { + let span = tracing::debug_span!("arg_of"); + let _entered = span.enter(); let is_return = arg_idx.is_none(); let layout = self.layout_of(ty)?; @@ -3368,6 +3375,7 @@ fn fn_abi_new_uncached( Ok(self.tcx.arena.alloc(fn_abi)) } + #[tracing::instrument(level = "debug", skip(self))] fn fn_abi_adjust_for_abi( &self, fn_abi: &mut FnAbi<'tcx, Ty<'tcx>>, @@ -3442,6 +3450,7 @@ fn fn_abi_adjust_for_abi( } } +#[tracing::instrument(level = "debug", skip(cx))] fn make_thin_self_ptr<'tcx>( cx: &(impl HasTyCtxt<'tcx> + HasParamEnv<'tcx>), layout: TyAndLayout<'tcx>, @@ -3453,7 +3462,7 @@ fn make_thin_self_ptr<'tcx>( tcx.mk_mut_ptr(layout.ty) } else { match layout.abi { - Abi::ScalarPair(..) => (), + Abi::ScalarPair(..) | Abi::Scalar(..) => (), _ => bug!("receiver type has unsupported layout: {:?}", layout), } diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index cac8560ce1c..9db5a289484 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -36,6 +36,7 @@ impl<'tcx> TyCtxt<'tcx> { /// /// This should only be used outside of type inference. For example, /// it assumes that normalization will succeed. + #[tracing::instrument(level = "debug", skip(self, param_env))] pub fn normalize_erasing_regions(self, param_env: ty::ParamEnv<'tcx>, value: T) -> T where T: TypeFoldable<'tcx>, @@ -100,6 +101,7 @@ pub fn try_normalize_erasing_regions( /// N.B., currently, higher-ranked type bounds inhibit /// normalization. Therefore, each time we erase them in /// codegen, we need to normalize the contents. + #[tracing::instrument(level = "debug", skip(self, param_env))] pub fn normalize_erasing_late_bound_regions( self, param_env: ty::ParamEnv<'tcx>, diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index f9394564f0e..98bdaf0bc62 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -216,10 +216,7 @@ pub(crate) fn as_rvalue( }; let from_ty = CastTy::from_ty(ty); let cast_ty = CastTy::from_ty(expr.ty); - debug!( - "ExprKind::Cast from_ty={from_ty:?}, cast_ty={:?}/{cast_ty:?}", - expr.ty, - ); + debug!("ExprKind::Cast from_ty={from_ty:?}, cast_ty={:?}/{cast_ty:?}", expr.ty,); let cast_kind = match (from_ty, cast_ty) { (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => { CastKind::PointerExposeAddress diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index be74a9d11e3..8b318d5e249 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -189,7 +189,8 @@ use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::{ - self, GenericParamDefKind, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitable, VtblEntry, + self, GenericParamDefKind, Instance, TraitObjectRepresentation, Ty, TyCtxt, TypeFoldable, + TypeVisitable, VtblEntry, }; use rustc_middle::{middle::codegen_fn_attrs::CodegenFnAttrFlags, mir::visit::TyContext}; use rustc_session::config::EntryFnType; @@ -689,7 +690,8 @@ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) { mir::CastKind::Pointer(PointerCast::Unsize), ref operand, target_ty, - ) => { + ) + | mir::Rvalue::Cast(mir::CastKind::DynStar, ref operand, target_ty) => { let target_ty = self.monomorphize(target_ty); let source_ty = operand.ty(self.body, self.tcx); let source_ty = self.monomorphize(source_ty); @@ -698,7 +700,7 @@ fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) { // This could also be a different Unsize instruction, like // from a fixed sized array to a slice. But we are only // interested in things that produce a vtable. - if target_ty.is_trait() && !source_ty.is_trait() { + if (target_ty.is_trait() || target_ty.is_dyn_star()) && !source_ty.is_trait() { create_mono_items_for_vtable_methods( self.tcx, target_ty, @@ -1112,6 +1114,11 @@ fn find_vtable_types_for_unsizing<'tcx>( ptr_vtable(source_ty.boxed_ty(), target_ty.boxed_ty()) } + // T as dyn* Trait + (_, &ty::Dynamic(_, _, TraitObjectRepresentation::Sized)) => { + ptr_vtable(source_ty, target_ty) + } + (&ty::Adt(source_adt_def, source_substs), &ty::Adt(target_adt_def, target_substs)) => { assert_eq!(source_adt_def, target_adt_def); diff --git a/src/test/ui/dyn-star/make-dyn-star.rs b/src/test/ui/dyn-star/make-dyn-star.rs index 593a4509f7d..b0b8f07abe5 100644 --- a/src/test/ui/dyn-star/make-dyn-star.rs +++ b/src/test/ui/dyn-star/make-dyn-star.rs @@ -4,7 +4,7 @@ use std::fmt::Debug; fn make_dyn_star(i: usize) { - let dyn_i: dyn* Debug = i as dyn* Debug; + let _dyn_i: dyn* Debug = i as dyn* Debug; } fn main() {