From 5e5e944b13d60a76ae10f47e18b3da5f67a8e8ca Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Sat, 15 Apr 2023 09:47:19 +0000 Subject: [PATCH] Only generate a single shim for clone of copy types. --- .../src/interpret/terminator.rs | 1 + compiler/rustc_middle/src/mir/mono.rs | 1 + compiler/rustc_middle/src/mir/visit.rs | 1 + compiler/rustc_middle/src/ty/instance.rs | 10 ++++- compiler/rustc_middle/src/ty/mod.rs | 1 + compiler/rustc_mir_transform/src/inline.rs | 1 + .../rustc_mir_transform/src/inline/cycle.rs | 1 + compiler/rustc_mir_transform/src/shim.rs | 42 +++++++++++-------- compiler/rustc_monomorphize/src/collector.rs | 1 + .../rustc_monomorphize/src/partitioning.rs | 2 + .../rustc_smir/src/rustc_smir/convert/ty.rs | 1 + compiler/rustc_ty_utils/src/instance.rs | 11 ++--- ...inline_shims.clone.Inline.panic-abort.diff | 2 +- ...nline_shims.clone.Inline.panic-unwind.diff | 2 +- tests/mir-opt/inline/inline_shims.rs | 2 +- 15 files changed, 50 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 2358caffc9b49..1e2dc23ce0bd3 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -544,6 +544,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::CloneShim(..) + | ty::InstanceDef::CloneCopyShim(..) | ty::InstanceDef::FnPtrAddrShim(..) | ty::InstanceDef::ThreadLocalShim(..) | ty::InstanceDef::Item(_) => { diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 91fdf0b312991..483ddc4cad020 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -404,6 +404,7 @@ impl<'tcx> CodegenUnit<'tcx> { | InstanceDef::ClosureOnceShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::CloneShim(..) + | InstanceDef::CloneCopyShim(..) | InstanceDef::ThreadLocalShim(..) | InstanceDef::FnPtrAddrShim(..) => None, } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 132ecf91af187..0584214e04bb4 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -344,6 +344,7 @@ macro_rules! make_mir_visitor { ty::InstanceDef::ReifyShim(_def_id) | ty::InstanceDef::Virtual(_def_id, _) | ty::InstanceDef::ThreadLocalShim(_def_id) | + ty::InstanceDef::CloneCopyShim(_def_id) | ty::InstanceDef::ClosureOnceShim { call_once: _def_id, track_caller: _ } | ty::InstanceDef::DropGlue(_def_id, None) => {} diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 1b6d59ab25777..5a973245079da 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -97,9 +97,13 @@ pub enum InstanceDef<'tcx> { /// glue. DropGlue(DefId, Option>), + /// Compiler-generated `::clone` implementation where T is `Copy`. + /// + /// The `DefId` is for `Clone::clone`. + CloneCopyShim(DefId), + /// Compiler-generated `::clone` implementation. /// - /// For all types that automatically implement `Copy`, a trivial `Clone` impl is provided too. /// Additionally, arrays, tuples, and closures get a `Clone` shim even if they aren't `Copy`. /// /// The `DefId` is for `Clone::clone`, the `Ty` is the type `T` with the builtin `Clone` impl. @@ -168,6 +172,7 @@ impl<'tcx> InstanceDef<'tcx> { | InstanceDef::ClosureOnceShim { call_once: def_id, track_caller: _ } | InstanceDef::DropGlue(def_id, _) | InstanceDef::CloneShim(def_id, _) + | InstanceDef::CloneCopyShim(def_id) | InstanceDef::FnPtrAddrShim(def_id, _) => def_id, } } @@ -187,6 +192,7 @@ impl<'tcx> InstanceDef<'tcx> { | InstanceDef::ClosureOnceShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::CloneShim(..) + | InstanceDef::CloneCopyShim(..) | InstanceDef::FnPtrAddrShim(..) => None, } } @@ -280,6 +286,7 @@ impl<'tcx> InstanceDef<'tcx> { | InstanceDef::FnPtrShim(..) | InstanceDef::DropGlue(_, Some(_)) => false, InstanceDef::ClosureOnceShim { .. } + | InstanceDef::CloneCopyShim(..) | InstanceDef::DropGlue(..) | InstanceDef::Item(_) | InstanceDef::Intrinsic(..) @@ -316,6 +323,7 @@ fn fmt_instance( InstanceDef::DropGlue(_, None) => write!(f, " - shim(None)"), InstanceDef::DropGlue(_, Some(ty)) => write!(f, " - shim(Some({ty}))"), InstanceDef::CloneShim(_, ty) => write!(f, " - shim({ty})"), + InstanceDef::CloneCopyShim(_) => write!(f, " - shim()"), InstanceDef::FnPtrAddrShim(_, ty) => write!(f, " - shim({ty})"), } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 0653796ec7fc3..7a1ac82ce564b 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2331,6 +2331,7 @@ impl<'tcx> TyCtxt<'tcx> { | ty::InstanceDef::ClosureOnceShim { .. } | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::CloneShim(..) + | ty::InstanceDef::CloneCopyShim(..) | ty::InstanceDef::ThreadLocalShim(..) | ty::InstanceDef::FnPtrAddrShim(..) => self.mir_shims(instance), } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 8ad804bf3e7aa..8e64a32e5bcf1 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -319,6 +319,7 @@ impl<'tcx> Inliner<'tcx> { | InstanceDef::ClosureOnceShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::CloneShim(..) + | InstanceDef::CloneCopyShim(..) | InstanceDef::ThreadLocalShim(..) | InstanceDef::FnPtrAddrShim(..) => return Ok(()), } diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index d30e0bad81301..9812c23e3e0e6 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -88,6 +88,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( | InstanceDef::FnPtrShim(..) | InstanceDef::ClosureOnceShim { .. } | InstanceDef::ThreadLocalShim { .. } + | InstanceDef::CloneCopyShim(..) | InstanceDef::CloneShim(..) => {} // This shim does not call any other functions, thus there can be no recursion. diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index f6b820bfcd01f..80a09f066e10e 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -1,15 +1,14 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::lang_items::LangItem; +use rustc_index::{Idx, IndexVec}; use rustc_middle::mir::*; use rustc_middle::query::Providers; use rustc_middle::ty::GenericArgs; use rustc_middle::ty::{self, CoroutineArgs, EarlyBinder, Ty, TyCtxt}; -use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; - -use rustc_index::{Idx, IndexVec}; - +use rustc_span::symbol::kw; use rustc_span::Span; +use rustc_target::abi::{FieldIdx, VariantIdx, FIRST_VARIANT}; use rustc_target::spec::abi::Abi; use std::fmt; @@ -90,7 +89,18 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' build_drop_shim(tcx, def_id, ty) } ty::InstanceDef::ThreadLocalShim(..) => build_thread_local_shim(tcx, instance), - ty::InstanceDef::CloneShim(def_id, ty) => build_clone_shim(tcx, def_id, ty), + ty::InstanceDef::CloneCopyShim(def_id) => { + let self_ty = Ty::new_param(tcx, 0, kw::SelfUpper); + let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty); + builder.copy_shim(); + let mut result = builder.into_mir(instance); + // Mark as runtime MIR to bypass MIR validation checking `Operand::Copy`. + result.phase = MirPhase::Runtime(RuntimePhase::Initial); + result + } + ty::InstanceDef::CloneShim(def_id, ty) => { + build_clone_shim(tcx, def_id, ty).into_mir(instance) + } ty::InstanceDef::FnPtrAddrShim(def_id, ty) => build_fn_ptr_addr_shim(tcx, def_id, ty), ty::InstanceDef::Virtual(..) => { bug!("InstanceDef::Virtual ({:?}) is for direct calls only", instance) @@ -379,19 +389,18 @@ fn build_thread_local_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'t } /// Builds a `Clone::clone` shim for `self_ty`. Here, `def_id` is `Clone::clone`. -fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) -> Body<'tcx> { - debug!("build_clone_shim(def_id={:?})", def_id); - - let param_env = tcx.param_env_reveal_all_normalized(def_id); - +#[instrument(level = "trace", skip(tcx))] +fn build_clone_shim<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: DefId, + self_ty: Ty<'tcx>, +) -> CloneShimBuilder<'tcx> { let mut builder = CloneShimBuilder::new(tcx, def_id, self_ty); - let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env); let dest = Place::return_place(); let src = tcx.mk_place_deref(Place::from(Local::new(1 + 0))); match self_ty.kind() { - _ if is_copy => builder.copy_shim(), ty::Closure(_, args) => builder.tuple_like_shim(dest, src, args.as_closure().upvar_tys()), ty::Tuple(..) => builder.tuple_like_shim(dest, src, self_ty.tuple_fields()), ty::Coroutine(coroutine_def_id, args) => { @@ -401,7 +410,7 @@ fn build_clone_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, self_ty: Ty<'tcx>) - _ => bug!("clone shim for `{:?}` which is not `Copy` and is not an aggregate", self_ty), }; - builder.into_mir() + builder } struct CloneShimBuilder<'tcx> { @@ -432,11 +441,8 @@ impl<'tcx> CloneShimBuilder<'tcx> { } } - fn into_mir(self) -> Body<'tcx> { - let source = MirSource::from_instance(ty::InstanceDef::CloneShim( - self.def_id, - self.sig.inputs_and_output[0], - )); + fn into_mir(self, def: ty::InstanceDef<'tcx>) -> Body<'tcx> { + let source = MirSource::from_instance(def); new_body(source, self.blocks, self.local_decls, self.sig.inputs().len(), self.span) } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 54464600d99a8..670cd5c565632 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -961,6 +961,7 @@ fn visit_instance_use<'tcx>( | ty::InstanceDef::Item(..) | ty::InstanceDef::FnPtrShim(..) | ty::InstanceDef::CloneShim(..) + | ty::InstanceDef::CloneCopyShim(..) | ty::InstanceDef::FnPtrAddrShim(..) => { output.push(create_fn_mono_item(tcx, instance, source)); } diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 08e628408394e..fd92cbfa79cdb 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -624,6 +624,7 @@ fn characteristic_def_id_of_mono_item<'tcx>( | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::Virtual(..) | ty::InstanceDef::CloneShim(..) + | ty::InstanceDef::CloneCopyShim(..) | ty::InstanceDef::ThreadLocalShim(..) | ty::InstanceDef::FnPtrAddrShim(..) => return None, }; @@ -785,6 +786,7 @@ fn mono_item_visibility<'tcx>( | InstanceDef::ClosureOnceShim { .. } | InstanceDef::DropGlue(..) | InstanceDef::CloneShim(..) + | InstanceDef::CloneCopyShim(..) | InstanceDef::FnPtrAddrShim(..) => return Visibility::Hidden, }; diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs index f0f1d798d44b4..de8de8fe46f81 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs @@ -799,6 +799,7 @@ impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> { | ty::InstanceDef::ThreadLocalShim(..) | ty::InstanceDef::DropGlue(..) | ty::InstanceDef::CloneShim(..) + | ty::InstanceDef::CloneCopyShim(..) | ty::InstanceDef::FnPtrShim(..) => stable_mir::mir::mono::InstanceKind::Shim, }; stable_mir::mir::mono::Instance { def, kind } diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 81d5304b81265..d2525993cb9e0 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -210,19 +210,16 @@ fn resolve_associated_item<'tcx>( let self_ty = trait_ref.self_ty(); let is_copy = self_ty.is_copy_modulo_regions(tcx, param_env); - match self_ty.kind() { - _ if is_copy => (), + let def = match self_ty.kind() { + _ if is_copy => ty::InstanceDef::CloneCopyShim(trait_item_id), ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Closure(..) - | ty::Tuple(..) => {} + | ty::Tuple(..) => ty::InstanceDef::CloneShim(trait_item_id, self_ty), _ => return Ok(None), }; - Some(Instance { - def: ty::InstanceDef::CloneShim(trait_item_id, self_ty), - args: rcvr_args, - }) + Some(Instance { def, args: rcvr_args }) } else { assert_eq!(name, sym::clone_from); diff --git a/tests/mir-opt/inline/inline_shims.clone.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_shims.clone.Inline.panic-abort.diff index 8117e58fa51a3..7ca852a42a101 100644 --- a/tests/mir-opt/inline/inline_shims.clone.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_shims.clone.Inline.panic-abort.diff @@ -5,7 +5,7 @@ debug f => _1; let mut _0: fn(A, B); let mut _2: &fn(A, B); -+ scope 1 (inlined ::clone - shim(fn(A, B))) { ++ scope 1 (inlined ::clone - shim()) { + } bb0: { diff --git a/tests/mir-opt/inline/inline_shims.clone.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_shims.clone.Inline.panic-unwind.diff index 00e92a0f5e5af..2baf6b98731f5 100644 --- a/tests/mir-opt/inline/inline_shims.clone.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_shims.clone.Inline.panic-unwind.diff @@ -5,7 +5,7 @@ debug f => _1; let mut _0: fn(A, B); let mut _2: &fn(A, B); -+ scope 1 (inlined ::clone - shim(fn(A, B))) { ++ scope 1 (inlined ::clone - shim()) { + } bb0: { diff --git a/tests/mir-opt/inline/inline_shims.rs b/tests/mir-opt/inline/inline_shims.rs index a223c2d2614b1..1c45353e2e8f5 100644 --- a/tests/mir-opt/inline/inline_shims.rs +++ b/tests/mir-opt/inline/inline_shims.rs @@ -4,7 +4,7 @@ // EMIT_MIR inline_shims.clone.Inline.diff pub fn clone(f: fn(A, B)) -> fn(A, B) { // CHECK-LABEL: fn clone( - // CHECK: (inlined ::clone - shim(fn(A, B))) + // CHECK: (inlined ::clone - shim()) f.clone() }